~ubuntu-branches/ubuntu/natty/libvirt/natty-security

« back to all changes in this revision

Viewing changes to .pc/0004-fix-Debian-specific-path-to-hvm-loader.patch/src/xen/xen_hypervisor.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-02-23 09:05:46 UTC
  • mfrom: (1.2.8 upstream) (3.4.25 sid)
  • Revision ID: james.westby@ubuntu.com-20110223090546-4pwmrrt7h51hr3l3
Tags: 0.8.8-1ubuntu1
* Resynchronize and merge from Debian unstable. Remaining changes:
  - debian/patches:
    * 9000-delayed_iff_up_bridge.patch
    * 9001-dont_clobber_existing_bridges.patch
    * 9002-better_default_uri_virsh.patch
    * 9003-better-default-arch.patch
    * 9004-libvirtd-group-name.patch
    * 9005-increase-unix-socket-timeout.patch
    * 9006-default-config-test-case.patch
    * 9007-fix-daemon-conf-ftbfs.patch
    * 9011-move-ebtables-script.patch
    * 9014-skip-nodeinfotest.patch
    * 9020-lp545795.patch
    * 9021-fix-uint64_t.patch
  - debian/patches/series:
    * Disable qemu-disable-network.diff.patch
  - debian/control:
    * set ubuntu maintainer
    * Build-Depends:
      - swap libxen to libxen3, qemu to qemu-kvm, and open-iscsi to
        open-iscsi-utils in Build-Depends
      - remove virtualbox Build-Depends
      - add libxml2 and libapparmor-dev Build-Depends
    * convert Vcs-Git to Xs-Debian-Vcs-Git
    * libvirt-bin Depends: move netcat-openbsd, bridge-utils, dnsmasq-base
      (>= 2.46-1), and iptables from Recommends to Depends
    * libvirt-bin Recommends: move qemu to Suggests
    * libvirt-bin Suggests: add apparmor
    * libvirt0 Recommands: move lvm2 to Suggests
  - keep debian/libvirt-bin.apport
  - keep debian/libvirt-bin.cron.daily
  - debian/libvirt-bin.dirs:
    * add apparmor, cron.daily, and apport dirs
  - debian/libvirt-bin.examples:
    * add debian/libvirt-suspendonreboot
  - debian/libvirt-bin.install:
    * add /etc/apparmor.d files
    * add apport hook
  - debian/libvirt-bin.manpages:
    * add debian/libvirt-migrate-qemu-disks.1
  - debian/libvirt-bin.postinst:
    * replace libvirt groupname with libvirtd
    * add each admin user to libvirtd group
    * call apparmor_parser on usr.sbin.libvirtd and
      usr.lib.libvirt.virt-aa-helper
    * call 'libvirt-migrate-qemu-disks -a' after
      libvirt-bin has started if migrating from
      older than 0.8.3-1ubuntu1
  - debian/libvirt-bin.postrm:
    * replace libvirt groupname with libvirtd
    * remove usr.sbin.libvirtd and
      usr.lib.libvirt.virt-aa-helper
  - keep added files under debian/:
    * libvirt-bin.upstart
    * libvirt-migrate-qemu-disks
    * libvirt-migrate-qemu-disks.1
    * libvirt-suspendonreboot
    * apparmor profiles
  - debian/README.Debian:
    * add 'Apparmor Profile' section
    * add 'Disk migration' section
  - debian/rules:
    * don't build with vbox since virtualbox-ose is in universe
    * add --with-apparmor to DEB_CONFIGURE_EXTRA_FLAGS
    * set DEB_DH_INSTALLINIT_ARGS to '--upstart-only'
    * set DEB_MAKE_CHECK_TARGET to 'check'
    * remove unneeded binary-install/libvirt-bin:: and clean::
      sections (they only deal with sysvinit stuff)
    * add build/libvirt-bin:: section to install
      - apparmor files
      - apport hooks
      - libvirt-migrate-qemu-disks
* The following Ubuntu packaging changes occurred during the divergence
  between Debian and Ubuntu. These changes are not new, but included here
  for completeness: (0.8.5-0ubuntu1 - 0.8.5-0ubuntu5):
  - Have upstart job source /etc/default/libvirt-bin.  This is only a
    temporary fix until upstart provides proper default override support
    through /etc/init/libvirt-bin.override (or any other mechanism).
    (LP: 708172)
  - debian/apparmor/usr.sbin.libvirtd: use PUx instead of Ux for executables
    (LP: 573315)
  - Rebuild with python 2.7 as the python default.
  - debian/libvirt-bin.cron.daily: use shell globbing to enumerate xml files.
    Based on patch thanks to Henryk Plötz (LP: 655176)
* Dropped the following patches included/fixed upstream:
  - 9010-dont-disable-ipv6.patch
  - 9022-build-cleanup-declaration-of-xen-tests.patch
  - 9023-vah-require-uuid.patch
  - 9009-autodetect-nc-params.patch
    * rolled into Debian's
      Autodetect-if-the-remote-nc-command-supports-the-q-o.patch
* Updated the following patches:
  - 9011-move-ebtables-script.patch:
    * LOCALSTATEDIR is defined in configmake.h
  - 9000-9006: added DEP-3 tags
  - 9002-better_default_uri_virsh.patch: updated (context changed)
* New patches:
  - 9022-drop-booton-when-kernel-specified.patch (LP: #720426)
  - 9023-fix-lxc-console-hangup.patch (LP: #668369)
  - 9024-skip-broken-commandtest.patch
* debian/patches/series:
  - don't apply Disable-CHECKSUM-rule.patch: our iptables can do this
  - don't apply Debian-specific Debianize-libvirt-guests.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * xen_internal.c: direct access to Xen hypervisor level
3
 
 *
4
 
 * Copyright (C) 2005-2010 Red Hat, Inc.
5
 
 *
6
 
 * See COPYING.LIB for the License of this software
7
 
 *
8
 
 * Daniel Veillard <veillard@redhat.com>
9
 
 */
10
 
 
11
 
#include <config.h>
12
 
 
13
 
#include <stdio.h>
14
 
#include <string.h>
15
 
/* required for uint8_t, uint32_t, etc ... */
16
 
#include <stdint.h>
17
 
#include <sys/types.h>
18
 
#include <sys/stat.h>
19
 
#include <unistd.h>
20
 
#include <fcntl.h>
21
 
#include <sys/mman.h>
22
 
#include <sys/ioctl.h>
23
 
#include <limits.h>
24
 
#include <stdint.h>
25
 
#include <regex.h>
26
 
#include <errno.h>
27
 
#include <sys/utsname.h>
28
 
 
29
 
#ifdef __sun
30
 
# include <sys/systeminfo.h>
31
 
 
32
 
# include <priv.h>
33
 
 
34
 
# ifndef PRIV_XVM_CONTROL
35
 
#  define PRIV_XVM_CONTROL ((const char *)"xvm_control")
36
 
# endif
37
 
 
38
 
#endif /* __sun */
39
 
 
40
 
/* required for dom0_getdomaininfo_t */
41
 
#include <xen/dom0_ops.h>
42
 
#include <xen/version.h>
43
 
#ifdef HAVE_XEN_LINUX_PRIVCMD_H
44
 
# include <xen/linux/privcmd.h>
45
 
#else
46
 
# ifdef HAVE_XEN_SYS_PRIVCMD_H
47
 
#  include <xen/sys/privcmd.h>
48
 
# endif
49
 
#endif
50
 
 
51
 
/* required for shutdown flags */
52
 
#include <xen/sched.h>
53
 
 
54
 
#include "virterror_internal.h"
55
 
#include "logging.h"
56
 
#include "datatypes.h"
57
 
#include "driver.h"
58
 
#include "util.h"
59
 
#include "xen_driver.h"
60
 
#include "xen_hypervisor.h"
61
 
#include "xs_internal.h"
62
 
#include "stats_linux.h"
63
 
#include "block_stats.h"
64
 
#include "xend_internal.h"
65
 
#include "buf.h"
66
 
#include "capabilities.h"
67
 
#include "memory.h"
68
 
 
69
 
#define VIR_FROM_THIS VIR_FROM_XEN
70
 
 
71
 
/*
72
 
 * so far there is 2 versions of the structures usable for doing
73
 
 * hypervisor calls.
74
 
 */
75
 
/* the old one */
76
 
typedef struct v0_hypercall_struct {
77
 
    unsigned long op;
78
 
    unsigned long arg[5];
79
 
} v0_hypercall_t;
80
 
 
81
 
#ifdef __linux__
82
 
# define XEN_V0_IOCTL_HYPERCALL_CMD \
83
 
        _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t))
84
 
/* the new one */
85
 
typedef struct v1_hypercall_struct
86
 
{
87
 
    uint64_t op;
88
 
    uint64_t arg[5];
89
 
} v1_hypercall_t;
90
 
# define XEN_V1_IOCTL_HYPERCALL_CMD                  \
91
 
    _IOC(_IOC_NONE, 'P', 0, sizeof(v1_hypercall_t))
92
 
typedef v1_hypercall_t hypercall_t;
93
 
#elif defined(__sun)
94
 
typedef privcmd_hypercall_t hypercall_t;
95
 
#else
96
 
# error "unsupported platform"
97
 
#endif
98
 
 
99
 
#ifndef __HYPERVISOR_sysctl
100
 
# define __HYPERVISOR_sysctl 35
101
 
#endif
102
 
#ifndef __HYPERVISOR_domctl
103
 
# define __HYPERVISOR_domctl 36
104
 
#endif
105
 
 
106
 
#ifdef WITH_RHEL5_API
107
 
# define SYS_IFACE_MIN_VERS_NUMA 3
108
 
#else
109
 
# define SYS_IFACE_MIN_VERS_NUMA 4
110
 
#endif
111
 
 
112
 
/* xen-unstable changeset 19788 removed MAX_VIRT_CPUS from public
113
 
 * headers.  Its semanitc was retained with XEN_LEGACY_MAX_VCPUS.
114
 
 * Ensure MAX_VIRT_CPUS is defined accordingly.
115
 
 */
116
 
#if !defined(MAX_VIRT_CPUS) && defined(XEN_LEGACY_MAX_VCPUS)
117
 
# define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS
118
 
#endif
119
 
 
120
 
static int xen_ioctl_hypercall_cmd = 0;
121
 
static int initialized = 0;
122
 
static int in_init = 0;
123
 
static int hv_version = 0;
124
 
static int hypervisor_version = 2;
125
 
static int sys_interface_version = -1;
126
 
static int dom_interface_version = -1;
127
 
static int kb_per_pages = 0;
128
 
 
129
 
/* Regular expressions used by xenHypervisorGetCapabilities, and
130
 
 * compiled once by xenHypervisorInit.  Note that these are POSIX.2
131
 
 * extended regular expressions (regex(7)).
132
 
 */
133
 
static const char *flags_hvm_re = "^flags[[:blank:]]+:.* (vmx|svm)[[:space:]]";
134
 
static regex_t flags_hvm_rec;
135
 
static const char *flags_pae_re = "^flags[[:blank:]]+:.* pae[[:space:]]";
136
 
static regex_t flags_pae_rec;
137
 
static const char *xen_cap_re = "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x86_64|ia64|powerpc64)(p|be)?";
138
 
static regex_t xen_cap_rec;
139
 
 
140
 
/*
141
 
 * The content of the structures for a getdomaininfolist system hypercall
142
 
 */
143
 
#ifndef DOMFLAGS_DYING
144
 
# define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
145
 
# define DOMFLAGS_HVM       (1<<1) /* Domain is HVM                           */
146
 
# define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
147
 
# define DOMFLAGS_PAUSED    (1<<3) /* Currently paused by control software.   */
148
 
# define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
149
 
# define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
150
 
# define DOMFLAGS_CPUMASK      255 /* CPU to which this domain is bound.      */
151
 
# define DOMFLAGS_CPUSHIFT       8
152
 
# define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code.  */
153
 
# define DOMFLAGS_SHUTDOWNSHIFT 16
154
 
#endif
155
 
 
156
 
/*
157
 
 * These flags explain why a system is in the state of "shutdown".  Normally,
158
 
 * They are defined in xen/sched.h
159
 
 */
160
 
#ifndef SHUTDOWN_poweroff
161
 
# define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
162
 
# define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
163
 
# define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
164
 
# define SHUTDOWN_crash      3  /* Tell controller we've crashed.             */
165
 
#endif
166
 
 
167
 
#define XEN_V0_OP_GETDOMAININFOLIST     38
168
 
#define XEN_V1_OP_GETDOMAININFOLIST     38
169
 
#define XEN_V2_OP_GETDOMAININFOLIST     6
170
 
 
171
 
struct xen_v0_getdomaininfo {
172
 
    domid_t  domain;    /* the domain number */
173
 
    uint32_t flags;     /* flags, see before */
174
 
    uint64_t tot_pages; /* total number of pages used */
175
 
    uint64_t max_pages; /* maximum number of pages allowed */
176
 
    unsigned long shared_info_frame; /* MFN of shared_info struct */
177
 
    uint64_t cpu_time;  /* CPU time used */
178
 
    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
179
 
    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
180
 
    uint32_t ssidref;
181
 
    xen_domain_handle_t handle;
182
 
};
183
 
typedef struct xen_v0_getdomaininfo xen_v0_getdomaininfo;
184
 
 
185
 
struct xen_v2_getdomaininfo {
186
 
    domid_t  domain;    /* the domain number */
187
 
    uint32_t flags;     /* flags, see before */
188
 
    uint64_t tot_pages; /* total number of pages used */
189
 
    uint64_t max_pages; /* maximum number of pages allowed */
190
 
    uint64_t shared_info_frame; /* MFN of shared_info struct */
191
 
    uint64_t cpu_time;  /* CPU time used */
192
 
    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
193
 
    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
194
 
    uint32_t ssidref;
195
 
    xen_domain_handle_t handle;
196
 
};
197
 
typedef struct xen_v2_getdomaininfo xen_v2_getdomaininfo;
198
 
 
199
 
 
200
 
/* As of Hypervisor Call v2,  DomCtl v5 we are now 8-byte aligned
201
 
   even on 32-bit archs when dealing with uint64_t */
202
 
#define ALIGN_64 __attribute__((aligned(8)))
203
 
 
204
 
struct xen_v2d5_getdomaininfo {
205
 
    domid_t  domain;    /* the domain number */
206
 
    uint32_t flags;     /* flags, see before */
207
 
    uint64_t tot_pages ALIGN_64;        /* total number of pages used */
208
 
    uint64_t max_pages ALIGN_64;        /* maximum number of pages allowed */
209
 
    uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
210
 
    uint64_t cpu_time ALIGN_64;  /* CPU time used */
211
 
    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
212
 
    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
213
 
    uint32_t ssidref;
214
 
    xen_domain_handle_t handle;
215
 
};
216
 
typedef struct xen_v2d5_getdomaininfo xen_v2d5_getdomaininfo;
217
 
 
218
 
struct xen_v2d6_getdomaininfo {
219
 
    domid_t  domain;    /* the domain number */
220
 
    uint32_t flags;     /* flags, see before */
221
 
    uint64_t tot_pages ALIGN_64;        /* total number of pages used */
222
 
    uint64_t max_pages ALIGN_64;        /* maximum number of pages allowed */
223
 
    uint64_t shr_pages ALIGN_64;    /* number of shared pages */
224
 
    uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
225
 
    uint64_t cpu_time ALIGN_64;  /* CPU time used */
226
 
    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
227
 
    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
228
 
    uint32_t ssidref;
229
 
    xen_domain_handle_t handle;
230
 
};
231
 
typedef struct xen_v2d6_getdomaininfo xen_v2d6_getdomaininfo;
232
 
 
233
 
union xen_getdomaininfo {
234
 
    struct xen_v0_getdomaininfo v0;
235
 
    struct xen_v2_getdomaininfo v2;
236
 
    struct xen_v2d5_getdomaininfo v2d5;
237
 
    struct xen_v2d6_getdomaininfo v2d6;
238
 
};
239
 
typedef union xen_getdomaininfo xen_getdomaininfo;
240
 
 
241
 
union xen_getdomaininfolist {
242
 
    struct xen_v0_getdomaininfo *v0;
243
 
    struct xen_v2_getdomaininfo *v2;
244
 
    struct xen_v2d5_getdomaininfo *v2d5;
245
 
    struct xen_v2d6_getdomaininfo *v2d6;
246
 
};
247
 
typedef union xen_getdomaininfolist xen_getdomaininfolist;
248
 
 
249
 
 
250
 
struct xen_v2_getschedulerid {
251
 
    uint32_t sched_id; /* Get Scheduler ID from Xen */
252
 
};
253
 
typedef struct xen_v2_getschedulerid xen_v2_getschedulerid;
254
 
 
255
 
 
256
 
union xen_getschedulerid {
257
 
    struct xen_v2_getschedulerid *v2;
258
 
};
259
 
typedef union xen_getschedulerid xen_getschedulerid;
260
 
 
261
 
struct xen_v2s4_availheap {
262
 
    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
263
 
    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
264
 
    int32_t  node;          /* NUMA node (-1 for sum across all nodes). */
265
 
    uint64_t avail_bytes;   /* Bytes available in the specified region. */
266
 
};
267
 
 
268
 
typedef struct xen_v2s4_availheap  xen_v2s4_availheap;
269
 
 
270
 
struct xen_v2s5_availheap {
271
 
    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
272
 
    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
273
 
    int32_t  node;          /* NUMA node (-1 for sum across all nodes). */
274
 
    uint64_t avail_bytes ALIGN_64;   /* Bytes available in the specified region. */
275
 
};
276
 
 
277
 
typedef struct xen_v2s5_availheap  xen_v2s5_availheap;
278
 
 
279
 
 
280
 
#define XEN_GETDOMAININFOLIST_ALLOC(domlist, size)                      \
281
 
    (hypervisor_version < 2 ?                                           \
282
 
     (VIR_ALLOC_N(domlist.v0, (size)) == 0) :                           \
283
 
     (dom_interface_version >= 6 ?                                      \
284
 
      (VIR_ALLOC_N(domlist.v2d6, (size)) == 0) :                        \
285
 
     (dom_interface_version == 5 ?                                      \
286
 
      (VIR_ALLOC_N(domlist.v2d5, (size)) == 0) :                        \
287
 
      (VIR_ALLOC_N(domlist.v2, (size)) == 0))))
288
 
 
289
 
#define XEN_GETDOMAININFOLIST_FREE(domlist)            \
290
 
    (hypervisor_version < 2 ?                          \
291
 
     VIR_FREE(domlist.v0) :                            \
292
 
     (dom_interface_version >= 6 ?                     \
293
 
      VIR_FREE(domlist.v2d6) :                         \
294
 
     (dom_interface_version == 5 ?                     \
295
 
      VIR_FREE(domlist.v2d5) :                         \
296
 
      VIR_FREE(domlist.v2))))
297
 
 
298
 
#define XEN_GETDOMAININFOLIST_CLEAR(domlist, size)            \
299
 
    (hypervisor_version < 2 ?                                 \
300
 
     memset(domlist.v0, 0, sizeof(*domlist.v0) * size) :      \
301
 
     (dom_interface_version >= 6 ?                            \
302
 
      memset(domlist.v2d6, 0, sizeof(*domlist.v2d6) * size) : \
303
 
     (dom_interface_version == 5 ?                            \
304
 
      memset(domlist.v2d5, 0, sizeof(*domlist.v2d5) * size) : \
305
 
      memset(domlist.v2, 0, sizeof(*domlist.v2) * size))))
306
 
 
307
 
#define XEN_GETDOMAININFOLIST_DOMAIN(domlist, n)    \
308
 
    (hypervisor_version < 2 ?                       \
309
 
     domlist.v0[n].domain :                         \
310
 
     (dom_interface_version >= 6 ?                  \
311
 
      domlist.v2d6[n].domain :                      \
312
 
     (dom_interface_version == 5 ?                  \
313
 
      domlist.v2d5[n].domain :                      \
314
 
      domlist.v2[n].domain)))
315
 
 
316
 
#define XEN_GETDOMAININFOLIST_UUID(domlist, n)      \
317
 
    (hypervisor_version < 2 ?                       \
318
 
     domlist.v0[n].handle :                         \
319
 
     (dom_interface_version >= 6 ?                  \
320
 
      domlist.v2d6[n].handle :                      \
321
 
     (dom_interface_version == 5 ?                  \
322
 
      domlist.v2d5[n].handle :                      \
323
 
      domlist.v2[n].handle)))
324
 
 
325
 
#define XEN_GETDOMAININFOLIST_DATA(domlist)        \
326
 
    (hypervisor_version < 2 ?                      \
327
 
     (void*)(domlist->v0) :                        \
328
 
     (dom_interface_version >= 6 ?                 \
329
 
      (void*)(domlist->v2d6) :                     \
330
 
     (dom_interface_version == 5 ?                 \
331
 
      (void*)(domlist->v2d5) :                     \
332
 
      (void*)(domlist->v2))))
333
 
 
334
 
#define XEN_GETDOMAININFO_SIZE                     \
335
 
    (hypervisor_version < 2 ?                      \
336
 
     sizeof(xen_v0_getdomaininfo) :                \
337
 
     (dom_interface_version >= 6 ?                 \
338
 
      sizeof(xen_v2d6_getdomaininfo) :             \
339
 
     (dom_interface_version == 5 ?                 \
340
 
      sizeof(xen_v2d5_getdomaininfo) :             \
341
 
      sizeof(xen_v2_getdomaininfo))))
342
 
 
343
 
#define XEN_GETDOMAININFO_CLEAR(dominfo)                           \
344
 
    (hypervisor_version < 2 ?                                      \
345
 
     memset(&(dominfo.v0), 0, sizeof(xen_v0_getdomaininfo)) :      \
346
 
     (dom_interface_version >= 6 ?                                 \
347
 
      memset(&(dominfo.v2d6), 0, sizeof(xen_v2d6_getdomaininfo)) : \
348
 
     (dom_interface_version == 5 ?                                 \
349
 
      memset(&(dominfo.v2d5), 0, sizeof(xen_v2d5_getdomaininfo)) : \
350
 
      memset(&(dominfo.v2), 0, sizeof(xen_v2_getdomaininfo)))))
351
 
 
352
 
#define XEN_GETDOMAININFO_DOMAIN(dominfo)       \
353
 
    (hypervisor_version < 2 ?                   \
354
 
     dominfo.v0.domain :                        \
355
 
     (dom_interface_version >= 6 ?              \
356
 
      dominfo.v2d6.domain :                     \
357
 
     (dom_interface_version == 5 ?              \
358
 
      dominfo.v2d5.domain :                     \
359
 
      dominfo.v2.domain)))
360
 
 
361
 
#define XEN_GETDOMAININFO_CPUTIME(dominfo)      \
362
 
    (hypervisor_version < 2 ?                   \
363
 
     dominfo.v0.cpu_time :                      \
364
 
     (dom_interface_version >= 6 ?              \
365
 
      dominfo.v2d6.cpu_time :                   \
366
 
     (dom_interface_version == 5 ?              \
367
 
      dominfo.v2d5.cpu_time :                   \
368
 
      dominfo.v2.cpu_time)))
369
 
 
370
 
 
371
 
#define XEN_GETDOMAININFO_CPUCOUNT(dominfo)     \
372
 
    (hypervisor_version < 2 ?                   \
373
 
     dominfo.v0.nr_online_vcpus :               \
374
 
     (dom_interface_version >= 6 ?              \
375
 
      dominfo.v2d6.nr_online_vcpus :            \
376
 
     (dom_interface_version == 5 ?              \
377
 
      dominfo.v2d5.nr_online_vcpus :            \
378
 
      dominfo.v2.nr_online_vcpus)))
379
 
 
380
 
#define XEN_GETDOMAININFO_MAXCPUID(dominfo)  \
381
 
    (hypervisor_version < 2 ?                   \
382
 
     dominfo.v0.max_vcpu_id :                   \
383
 
     (dom_interface_version >= 6 ?              \
384
 
      dominfo.v2d6.max_vcpu_id :                \
385
 
     (dom_interface_version == 5 ?              \
386
 
      dominfo.v2d5.max_vcpu_id :                \
387
 
      dominfo.v2.max_vcpu_id)))
388
 
 
389
 
#define XEN_GETDOMAININFO_FLAGS(dominfo)        \
390
 
    (hypervisor_version < 2 ?                   \
391
 
     dominfo.v0.flags :                         \
392
 
     (dom_interface_version >= 6 ?              \
393
 
      dominfo.v2d6.flags :                      \
394
 
     (dom_interface_version == 5 ?              \
395
 
      dominfo.v2d5.flags :                      \
396
 
      dominfo.v2.flags)))
397
 
 
398
 
#define XEN_GETDOMAININFO_TOT_PAGES(dominfo)    \
399
 
    (hypervisor_version < 2 ?                   \
400
 
     dominfo.v0.tot_pages :                     \
401
 
     (dom_interface_version >= 6 ?              \
402
 
      dominfo.v2d6.tot_pages :                  \
403
 
     (dom_interface_version == 5 ?              \
404
 
      dominfo.v2d5.tot_pages :                  \
405
 
      dominfo.v2.tot_pages)))
406
 
 
407
 
#define XEN_GETDOMAININFO_MAX_PAGES(dominfo)    \
408
 
    (hypervisor_version < 2 ?                   \
409
 
     dominfo.v0.max_pages :                     \
410
 
     (dom_interface_version >= 6 ?              \
411
 
      dominfo.v2d6.max_pages :                  \
412
 
     (dom_interface_version == 5 ?              \
413
 
      dominfo.v2d5.max_pages :                  \
414
 
      dominfo.v2.max_pages)))
415
 
 
416
 
#define XEN_GETDOMAININFO_UUID(dominfo)         \
417
 
    (hypervisor_version < 2 ?                   \
418
 
     dominfo.v0.handle :                        \
419
 
     (dom_interface_version >= 6 ?              \
420
 
      dominfo.v2d6.handle :                     \
421
 
     (dom_interface_version == 5 ?              \
422
 
      dominfo.v2d5.handle :                     \
423
 
      dominfo.v2.handle)))
424
 
 
425
 
 
426
 
static int
427
 
lock_pages(void *addr, size_t len)
428
 
{
429
 
#ifdef __linux__
430
 
        return (mlock(addr, len));
431
 
#elif defined(__sun)
432
 
        return (0);
433
 
#endif
434
 
}
435
 
 
436
 
static int
437
 
unlock_pages(void *addr, size_t len)
438
 
{
439
 
#ifdef __linux__
440
 
        return (munlock(addr, len));
441
 
#elif defined(__sun)
442
 
        return (0);
443
 
#endif
444
 
}
445
 
 
446
 
 
447
 
struct xen_v0_getdomaininfolistop {
448
 
    domid_t   first_domain;
449
 
    uint32_t  max_domains;
450
 
    struct xen_v0_getdomaininfo *buffer;
451
 
    uint32_t  num_domains;
452
 
};
453
 
typedef struct xen_v0_getdomaininfolistop xen_v0_getdomaininfolistop;
454
 
 
455
 
 
456
 
struct xen_v2_getdomaininfolistop {
457
 
    domid_t   first_domain;
458
 
    uint32_t  max_domains;
459
 
    struct xen_v2_getdomaininfo *buffer;
460
 
    uint32_t  num_domains;
461
 
};
462
 
typedef struct xen_v2_getdomaininfolistop xen_v2_getdomaininfolistop;
463
 
 
464
 
/* As of HV version 2, sysctl version 3 the *buffer pointer is 64-bit aligned */
465
 
struct xen_v2s3_getdomaininfolistop {
466
 
    domid_t   first_domain;
467
 
    uint32_t  max_domains;
468
 
#ifdef __BIG_ENDIAN__
469
 
    struct {
470
 
        int __pad[(sizeof (long long) - sizeof (struct xen_v2d5_getdomaininfo *)) / sizeof (int)];
471
 
        struct xen_v2d5_getdomaininfo *v;
472
 
    } buffer;
473
 
#else
474
 
    union {
475
 
        struct xen_v2d5_getdomaininfo *v;
476
 
        uint64_t pad ALIGN_64;
477
 
    } buffer;
478
 
#endif
479
 
    uint32_t  num_domains;
480
 
};
481
 
typedef struct xen_v2s3_getdomaininfolistop xen_v2s3_getdomaininfolistop;
482
 
 
483
 
 
484
 
 
485
 
struct xen_v0_domainop {
486
 
    domid_t   domain;
487
 
};
488
 
typedef struct xen_v0_domainop xen_v0_domainop;
489
 
 
490
 
/*
491
 
 * The information for a destroydomain system hypercall
492
 
 */
493
 
#define XEN_V0_OP_DESTROYDOMAIN 9
494
 
#define XEN_V1_OP_DESTROYDOMAIN 9
495
 
#define XEN_V2_OP_DESTROYDOMAIN 2
496
 
 
497
 
/*
498
 
 * The information for a pausedomain system hypercall
499
 
 */
500
 
#define XEN_V0_OP_PAUSEDOMAIN   10
501
 
#define XEN_V1_OP_PAUSEDOMAIN   10
502
 
#define XEN_V2_OP_PAUSEDOMAIN   3
503
 
 
504
 
/*
505
 
 * The information for an unpausedomain system hypercall
506
 
 */
507
 
#define XEN_V0_OP_UNPAUSEDOMAIN 11
508
 
#define XEN_V1_OP_UNPAUSEDOMAIN 11
509
 
#define XEN_V2_OP_UNPAUSEDOMAIN 4
510
 
 
511
 
/*
512
 
 * The information for an setmaxmem system hypercall
513
 
 */
514
 
#define XEN_V0_OP_SETMAXMEM     28
515
 
#define XEN_V1_OP_SETMAXMEM     28
516
 
#define XEN_V2_OP_SETMAXMEM     11
517
 
 
518
 
struct xen_v0_setmaxmem {
519
 
    domid_t     domain;
520
 
    uint64_t    maxmem;
521
 
};
522
 
typedef struct xen_v0_setmaxmem xen_v0_setmaxmem;
523
 
typedef struct xen_v0_setmaxmem xen_v1_setmaxmem;
524
 
 
525
 
struct xen_v2_setmaxmem {
526
 
    uint64_t    maxmem;
527
 
};
528
 
typedef struct xen_v2_setmaxmem xen_v2_setmaxmem;
529
 
 
530
 
struct xen_v2d5_setmaxmem {
531
 
    uint64_t    maxmem ALIGN_64;
532
 
};
533
 
typedef struct xen_v2d5_setmaxmem xen_v2d5_setmaxmem;
534
 
 
535
 
/*
536
 
 * The information for an setmaxvcpu system hypercall
537
 
 */
538
 
#define XEN_V0_OP_SETMAXVCPU    41
539
 
#define XEN_V1_OP_SETMAXVCPU    41
540
 
#define XEN_V2_OP_SETMAXVCPU    15
541
 
 
542
 
struct xen_v0_setmaxvcpu {
543
 
    domid_t     domain;
544
 
    uint32_t    maxvcpu;
545
 
};
546
 
typedef struct xen_v0_setmaxvcpu xen_v0_setmaxvcpu;
547
 
typedef struct xen_v0_setmaxvcpu xen_v1_setmaxvcpu;
548
 
 
549
 
struct xen_v2_setmaxvcpu {
550
 
    uint32_t    maxvcpu;
551
 
};
552
 
typedef struct xen_v2_setmaxvcpu xen_v2_setmaxvcpu;
553
 
 
554
 
/*
555
 
 * The information for an setvcpumap system hypercall
556
 
 * Note that between 1 and 2 the limitation to 64 physical CPU was lifted
557
 
 * hence the difference in structures
558
 
 */
559
 
#define XEN_V0_OP_SETVCPUMAP    20
560
 
#define XEN_V1_OP_SETVCPUMAP    20
561
 
#define XEN_V2_OP_SETVCPUMAP    9
562
 
 
563
 
struct xen_v0_setvcpumap {
564
 
    domid_t     domain;
565
 
    uint32_t    vcpu;
566
 
    cpumap_t    cpumap;
567
 
};
568
 
typedef struct xen_v0_setvcpumap xen_v0_setvcpumap;
569
 
typedef struct xen_v0_setvcpumap xen_v1_setvcpumap;
570
 
 
571
 
struct xen_v2_cpumap {
572
 
    uint8_t    *bitmap;
573
 
    uint32_t    nr_cpus;
574
 
};
575
 
struct xen_v2_setvcpumap {
576
 
    uint32_t    vcpu;
577
 
    struct xen_v2_cpumap cpumap;
578
 
};
579
 
typedef struct xen_v2_setvcpumap xen_v2_setvcpumap;
580
 
 
581
 
/* HV version 2, Dom version 5 requires 64-bit alignment */
582
 
struct xen_v2d5_cpumap {
583
 
#ifdef __BIG_ENDIAN__
584
 
    struct {
585
 
        int __pad[(sizeof (long long) - sizeof (uint8_t *)) / sizeof (int)];
586
 
        uint8_t *v;
587
 
    } bitmap;
588
 
#else
589
 
    union {
590
 
        uint8_t    *v;
591
 
        uint64_t   pad ALIGN_64;
592
 
    } bitmap;
593
 
#endif
594
 
    uint32_t    nr_cpus;
595
 
};
596
 
struct xen_v2d5_setvcpumap {
597
 
    uint32_t    vcpu;
598
 
    struct xen_v2d5_cpumap cpumap;
599
 
};
600
 
typedef struct xen_v2d5_setvcpumap xen_v2d5_setvcpumap;
601
 
 
602
 
/*
603
 
 * The information for an vcpuinfo system hypercall
604
 
 */
605
 
#define XEN_V0_OP_GETVCPUINFO   43
606
 
#define XEN_V1_OP_GETVCPUINFO   43
607
 
#define XEN_V2_OP_GETVCPUINFO   14
608
 
 
609
 
struct xen_v0_vcpuinfo {
610
 
    domid_t     domain;         /* owner's domain */
611
 
    uint32_t    vcpu;           /* the vcpu number */
612
 
    uint8_t     online;         /* seen as on line */
613
 
    uint8_t     blocked;        /* blocked on event */
614
 
    uint8_t     running;        /* scheduled on CPU */
615
 
    uint64_t    cpu_time;       /* nanosecond of CPU used */
616
 
    uint32_t    cpu;            /* current mapping */
617
 
    cpumap_t    cpumap;         /* deprecated in V2 */
618
 
};
619
 
typedef struct xen_v0_vcpuinfo xen_v0_vcpuinfo;
620
 
typedef struct xen_v0_vcpuinfo xen_v1_vcpuinfo;
621
 
 
622
 
struct xen_v2_vcpuinfo {
623
 
    uint32_t    vcpu;           /* the vcpu number */
624
 
    uint8_t     online;         /* seen as on line */
625
 
    uint8_t     blocked;        /* blocked on event */
626
 
    uint8_t     running;        /* scheduled on CPU */
627
 
    uint64_t    cpu_time;       /* nanosecond of CPU used */
628
 
    uint32_t    cpu;            /* current mapping */
629
 
};
630
 
typedef struct xen_v2_vcpuinfo xen_v2_vcpuinfo;
631
 
 
632
 
struct xen_v2d5_vcpuinfo {
633
 
    uint32_t    vcpu;           /* the vcpu number */
634
 
    uint8_t     online;         /* seen as on line */
635
 
    uint8_t     blocked;        /* blocked on event */
636
 
    uint8_t     running;        /* scheduled on CPU */
637
 
    uint64_t    cpu_time ALIGN_64; /* nanosecond of CPU used */
638
 
    uint32_t    cpu;            /* current mapping */
639
 
};
640
 
typedef struct xen_v2d5_vcpuinfo xen_v2d5_vcpuinfo;
641
 
 
642
 
/*
643
 
 * from V2 the pinning of a vcpu is read with a separate call
644
 
 */
645
 
#define XEN_V2_OP_GETVCPUMAP    25
646
 
typedef struct xen_v2_setvcpumap xen_v2_getvcpumap;
647
 
typedef struct xen_v2d5_setvcpumap xen_v2d5_getvcpumap;
648
 
 
649
 
/*
650
 
 * from V2 we get the scheduler information
651
 
 */
652
 
#define XEN_V2_OP_GETSCHEDULERID        4
653
 
 
654
 
/*
655
 
 * from V2 we get the available heap information
656
 
 */
657
 
#define XEN_V2_OP_GETAVAILHEAP          9
658
 
 
659
 
/*
660
 
 * from V2 we get the scheduler parameter
661
 
 */
662
 
#define XEN_V2_OP_SCHEDULER             16
663
 
/* Scheduler types. */
664
 
#define XEN_SCHEDULER_SEDF       4
665
 
#define XEN_SCHEDULER_CREDIT     5
666
 
/* get/set scheduler parameters */
667
 
#define XEN_DOMCTL_SCHEDOP_putinfo 0
668
 
#define XEN_DOMCTL_SCHEDOP_getinfo 1
669
 
 
670
 
struct xen_v2_setschedinfo {
671
 
    uint32_t sched_id;
672
 
    uint32_t cmd;
673
 
    union {
674
 
        struct xen_domctl_sched_sedf {
675
 
            uint64_t period ALIGN_64;
676
 
            uint64_t slice  ALIGN_64;
677
 
            uint64_t latency ALIGN_64;
678
 
            uint32_t extratime;
679
 
            uint32_t weight;
680
 
        } sedf;
681
 
        struct xen_domctl_sched_credit {
682
 
            uint16_t weight;
683
 
            uint16_t cap;
684
 
        } credit;
685
 
    } u;
686
 
};
687
 
typedef struct xen_v2_setschedinfo xen_v2_setschedinfo;
688
 
typedef struct xen_v2_setschedinfo xen_v2_getschedinfo;
689
 
 
690
 
 
691
 
/*
692
 
 * The hypercall operation structures also have changed on
693
 
 * changeset 86d26e6ec89b
694
 
 */
695
 
/* the old structure */
696
 
struct xen_op_v0 {
697
 
    uint32_t cmd;
698
 
    uint32_t interface_version;
699
 
    union {
700
 
        xen_v0_getdomaininfolistop getdomaininfolist;
701
 
        xen_v0_domainop          domain;
702
 
        xen_v0_setmaxmem         setmaxmem;
703
 
        xen_v0_setmaxvcpu        setmaxvcpu;
704
 
        xen_v0_setvcpumap        setvcpumap;
705
 
        xen_v0_vcpuinfo          getvcpuinfo;
706
 
        uint8_t padding[128];
707
 
    } u;
708
 
};
709
 
typedef struct xen_op_v0 xen_op_v0;
710
 
typedef struct xen_op_v0 xen_op_v1;
711
 
 
712
 
/* the new structure for systems operations */
713
 
struct xen_op_v2_sys {
714
 
    uint32_t cmd;
715
 
    uint32_t interface_version;
716
 
    union {
717
 
        xen_v2_getdomaininfolistop   getdomaininfolist;
718
 
        xen_v2s3_getdomaininfolistop getdomaininfolists3;
719
 
        xen_v2_getschedulerid        getschedulerid;
720
 
        xen_v2s4_availheap           availheap;
721
 
        xen_v2s5_availheap           availheap5;
722
 
        uint8_t padding[128];
723
 
    } u;
724
 
};
725
 
typedef struct xen_op_v2_sys xen_op_v2_sys;
726
 
 
727
 
/* the new structure for domains operation */
728
 
struct xen_op_v2_dom {
729
 
    uint32_t cmd;
730
 
    uint32_t interface_version;
731
 
    domid_t  domain;
732
 
    union {
733
 
        xen_v2_setmaxmem         setmaxmem;
734
 
        xen_v2d5_setmaxmem       setmaxmemd5;
735
 
        xen_v2_setmaxvcpu        setmaxvcpu;
736
 
        xen_v2_setvcpumap        setvcpumap;
737
 
        xen_v2d5_setvcpumap      setvcpumapd5;
738
 
        xen_v2_vcpuinfo          getvcpuinfo;
739
 
        xen_v2d5_vcpuinfo        getvcpuinfod5;
740
 
        xen_v2_getvcpumap        getvcpumap;
741
 
        xen_v2d5_getvcpumap      getvcpumapd5;
742
 
        xen_v2_setschedinfo      setschedinfo;
743
 
        xen_v2_getschedinfo      getschedinfo;
744
 
        uint8_t padding[128];
745
 
    } u;
746
 
};
747
 
typedef struct xen_op_v2_dom xen_op_v2_dom;
748
 
 
749
 
 
750
 
#ifdef __linux__
751
 
# define XEN_HYPERVISOR_SOCKET  "/proc/xen/privcmd"
752
 
# define HYPERVISOR_CAPABILITIES        "/sys/hypervisor/properties/capabilities"
753
 
#elif defined(__sun)
754
 
# define XEN_HYPERVISOR_SOCKET  "/dev/xen/privcmd"
755
 
#else
756
 
# error "unsupported platform"
757
 
#endif
758
 
 
759
 
#ifndef PROXY
760
 
static unsigned long xenHypervisorGetMaxMemory(virDomainPtr domain);
761
 
#endif
762
 
 
763
 
#ifndef PROXY
764
 
struct xenUnifiedDriver xenHypervisorDriver = {
765
 
    xenHypervisorOpen, /* open */
766
 
    xenHypervisorClose, /* close */
767
 
    xenHypervisorGetVersion, /* version */
768
 
    NULL, /* hostname */
769
 
    NULL, /* nodeGetInfo */
770
 
    xenHypervisorGetCapabilities, /* getCapabilities */
771
 
    xenHypervisorListDomains, /* listDomains */
772
 
    xenHypervisorNumOfDomains, /* numOfDomains */
773
 
    NULL, /* domainCreateXML */
774
 
    xenHypervisorPauseDomain, /* domainSuspend */
775
 
    xenHypervisorResumeDomain, /* domainResume */
776
 
    NULL, /* domainShutdown */
777
 
    NULL, /* domainReboot */
778
 
    xenHypervisorDestroyDomain, /* domainDestroy */
779
 
    xenHypervisorDomainGetOSType, /* domainGetOSType */
780
 
    xenHypervisorGetMaxMemory, /* domainGetMaxMemory */
781
 
    xenHypervisorSetMaxMemory, /* domainSetMaxMemory */
782
 
    NULL, /* domainSetMemory */
783
 
    xenHypervisorGetDomainInfo, /* domainGetInfo */
784
 
    NULL, /* domainSave */
785
 
    NULL, /* domainRestore */
786
 
    NULL, /* domainCoreDump */
787
 
    xenHypervisorPinVcpu, /* domainPinVcpu */
788
 
    xenHypervisorGetVcpus, /* domainGetVcpus */
789
 
    NULL, /* listDefinedDomains */
790
 
    NULL, /* numOfDefinedDomains */
791
 
    NULL, /* domainCreate */
792
 
    NULL, /* domainDefineXML */
793
 
    NULL, /* domainUndefine */
794
 
    NULL, /* domainAttachDeviceFlags */
795
 
    NULL, /* domainDetachDeviceFlags */
796
 
    NULL, /* domainUpdateDeviceFlags */
797
 
    NULL, /* domainGetAutostart */
798
 
    NULL, /* domainSetAutostart */
799
 
    xenHypervisorGetSchedulerType, /* domainGetSchedulerType */
800
 
    xenHypervisorGetSchedulerParameters, /* domainGetSchedulerParameters */
801
 
    xenHypervisorSetSchedulerParameters, /* domainSetSchedulerParameters */
802
 
};
803
 
#endif /* !PROXY */
804
 
 
805
 
#define virXenError(code, ...)                                             \
806
 
        if (in_init == 0)                                                  \
807
 
            virReportErrorHelper(NULL, VIR_FROM_XEN, code, __FILE__,       \
808
 
                                 __FUNCTION__, __LINE__, __VA_ARGS__)
809
 
 
810
 
#ifndef PROXY
811
 
 
812
 
/**
813
 
 * virXenErrorFunc:
814
 
 * @error: the error number
815
 
 * @func: the function failing
816
 
 * @info: extra information string
817
 
 * @value: extra information number
818
 
 *
819
 
 * Handle an error at the xend daemon interface
820
 
 */
821
 
static void
822
 
virXenErrorFunc(virErrorNumber error, const char *func, const char *info,
823
 
                int value)
824
 
{
825
 
    char fullinfo[1000];
826
 
    const char *errmsg;
827
 
 
828
 
    if ((error == VIR_ERR_OK) || (in_init != 0))
829
 
        return;
830
 
 
831
 
 
832
 
    errmsg =virErrorMsg(error, info);
833
 
    if (func != NULL) {
834
 
        snprintf(fullinfo, 999, "%s: %s", func, info);
835
 
        fullinfo[999] = 0;
836
 
        virRaiseError(NULL, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
837
 
                        errmsg, fullinfo, NULL, value, 0, errmsg, fullinfo,
838
 
                        value);
839
 
    } else {
840
 
        virRaiseError(NULL, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
841
 
                        errmsg, info, NULL, value, 0, errmsg, info,
842
 
                        value);
843
 
    }
844
 
}
845
 
 
846
 
#endif /* PROXY */
847
 
 
848
 
/**
849
 
 * xenHypervisorDoV0Op:
850
 
 * @handle: the handle to the Xen hypervisor
851
 
 * @op: pointer to the hypervisor operation structure
852
 
 *
853
 
 * Do an hypervisor operation though the old interface,
854
 
 * this leads to an hypervisor call through ioctl.
855
 
 *
856
 
 * Returns 0 in case of success and -1 in case of error.
857
 
 */
858
 
static int
859
 
xenHypervisorDoV0Op(int handle, xen_op_v0 * op)
860
 
{
861
 
    int ret;
862
 
    v0_hypercall_t hc;
863
 
 
864
 
    memset(&hc, 0, sizeof(hc));
865
 
    op->interface_version = hv_version << 8;
866
 
    hc.op = __HYPERVISOR_dom0_op;
867
 
    hc.arg[0] = (unsigned long) op;
868
 
 
869
 
    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
870
 
        virXenError(VIR_ERR_XEN_CALL, " locking");
871
 
        return (-1);
872
 
    }
873
 
 
874
 
    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
875
 
    if (ret < 0) {
876
 
        virXenError(VIR_ERR_XEN_CALL, " ioctl %d",
877
 
                    xen_ioctl_hypercall_cmd);
878
 
    }
879
 
 
880
 
    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
881
 
        virXenError(VIR_ERR_XEN_CALL, " releasing");
882
 
        ret = -1;
883
 
    }
884
 
 
885
 
    if (ret < 0)
886
 
        return (-1);
887
 
 
888
 
    return (0);
889
 
}
890
 
/**
891
 
 * xenHypervisorDoV1Op:
892
 
 * @handle: the handle to the Xen hypervisor
893
 
 * @op: pointer to the hypervisor operation structure
894
 
 *
895
 
 * Do an hypervisor v1 operation, this leads to an hypervisor call through
896
 
 * ioctl.
897
 
 *
898
 
 * Returns 0 in case of success and -1 in case of error.
899
 
 */
900
 
static int
901
 
xenHypervisorDoV1Op(int handle, xen_op_v1* op)
902
 
{
903
 
    int ret;
904
 
    hypercall_t hc;
905
 
 
906
 
    memset(&hc, 0, sizeof(hc));
907
 
    op->interface_version = DOM0_INTERFACE_VERSION;
908
 
    hc.op = __HYPERVISOR_dom0_op;
909
 
    hc.arg[0] = (unsigned long) op;
910
 
 
911
 
    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
912
 
        virXenError(VIR_ERR_XEN_CALL, " locking");
913
 
        return (-1);
914
 
    }
915
 
 
916
 
    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
917
 
    if (ret < 0) {
918
 
        virXenError(VIR_ERR_XEN_CALL, " ioctl %d",
919
 
                    xen_ioctl_hypercall_cmd);
920
 
    }
921
 
 
922
 
    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
923
 
        virXenError(VIR_ERR_XEN_CALL, " releasing");
924
 
        ret = -1;
925
 
    }
926
 
 
927
 
    if (ret < 0)
928
 
        return (-1);
929
 
 
930
 
    return (0);
931
 
}
932
 
 
933
 
/**
934
 
 * xenHypervisorDoV2Sys:
935
 
 * @handle: the handle to the Xen hypervisor
936
 
 * @op: pointer to the hypervisor operation structure
937
 
 *
938
 
 * Do an hypervisor v2 system operation, this leads to an hypervisor
939
 
 * call through ioctl.
940
 
 *
941
 
 * Returns 0 in case of success and -1 in case of error.
942
 
 */
943
 
static int
944
 
xenHypervisorDoV2Sys(int handle, xen_op_v2_sys* op)
945
 
{
946
 
    int ret;
947
 
    hypercall_t hc;
948
 
 
949
 
    memset(&hc, 0, sizeof(hc));
950
 
    op->interface_version = sys_interface_version;
951
 
    hc.op = __HYPERVISOR_sysctl;
952
 
    hc.arg[0] = (unsigned long) op;
953
 
 
954
 
    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
955
 
        virXenError(VIR_ERR_XEN_CALL, " locking");
956
 
        return (-1);
957
 
    }
958
 
 
959
 
    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
960
 
    if (ret < 0) {
961
 
        virXenError(VIR_ERR_XEN_CALL, " sys ioctl %d",
962
 
                                            xen_ioctl_hypercall_cmd);
963
 
    }
964
 
 
965
 
    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
966
 
        virXenError(VIR_ERR_XEN_CALL, " releasing");
967
 
        ret = -1;
968
 
    }
969
 
 
970
 
    if (ret < 0)
971
 
        return (-1);
972
 
 
973
 
    return (0);
974
 
}
975
 
 
976
 
/**
977
 
 * xenHypervisorDoV2Dom:
978
 
 * @handle: the handle to the Xen hypervisor
979
 
 * @op: pointer to the hypervisor domain operation structure
980
 
 *
981
 
 * Do an hypervisor v2 domain operation, this leads to an hypervisor
982
 
 * call through ioctl.
983
 
 *
984
 
 * Returns 0 in case of success and -1 in case of error.
985
 
 */
986
 
static int
987
 
xenHypervisorDoV2Dom(int handle, xen_op_v2_dom* op)
988
 
{
989
 
    int ret;
990
 
    hypercall_t hc;
991
 
 
992
 
    memset(&hc, 0, sizeof(hc));
993
 
    op->interface_version = dom_interface_version;
994
 
    hc.op = __HYPERVISOR_domctl;
995
 
    hc.arg[0] = (unsigned long) op;
996
 
 
997
 
    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
998
 
        virXenError(VIR_ERR_XEN_CALL, " locking");
999
 
        return (-1);
1000
 
    }
1001
 
 
1002
 
    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
1003
 
    if (ret < 0) {
1004
 
        virXenError(VIR_ERR_XEN_CALL, " ioctl %d",
1005
 
                    xen_ioctl_hypercall_cmd);
1006
 
    }
1007
 
 
1008
 
    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
1009
 
        virXenError(VIR_ERR_XEN_CALL, " releasing");
1010
 
        ret = -1;
1011
 
    }
1012
 
 
1013
 
    if (ret < 0)
1014
 
        return (-1);
1015
 
 
1016
 
    return (0);
1017
 
}
1018
 
 
1019
 
/**
1020
 
 * virXen_getdomaininfolist:
1021
 
 * @handle: the hypervisor handle
1022
 
 * @first_domain: first domain in the range
1023
 
 * @maxids: maximum number of domains to list
1024
 
 * @dominfos: output structures
1025
 
 *
1026
 
 * Do a low level hypercall to list existing domains information
1027
 
 *
1028
 
 * Returns the number of domains or -1 in case of failure
1029
 
 */
1030
 
static int
1031
 
virXen_getdomaininfolist(int handle, int first_domain, int maxids,
1032
 
                         xen_getdomaininfolist *dominfos)
1033
 
{
1034
 
    int ret = -1;
1035
 
 
1036
 
    if (lock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
1037
 
              XEN_GETDOMAININFO_SIZE * maxids) < 0) {
1038
 
        virXenError(VIR_ERR_XEN_CALL, " locking");
1039
 
        return (-1);
1040
 
    }
1041
 
    if (hypervisor_version > 1) {
1042
 
        xen_op_v2_sys op;
1043
 
 
1044
 
        memset(&op, 0, sizeof(op));
1045
 
        op.cmd = XEN_V2_OP_GETDOMAININFOLIST;
1046
 
 
1047
 
        if (sys_interface_version < 3) {
1048
 
            op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
1049
 
            op.u.getdomaininfolist.max_domains = maxids;
1050
 
            op.u.getdomaininfolist.buffer = dominfos->v2;
1051
 
            op.u.getdomaininfolist.num_domains = maxids;
1052
 
        } else {
1053
 
            op.u.getdomaininfolists3.first_domain = (domid_t) first_domain;
1054
 
            op.u.getdomaininfolists3.max_domains = maxids;
1055
 
            op.u.getdomaininfolists3.buffer.v = dominfos->v2d5;
1056
 
            op.u.getdomaininfolists3.num_domains = maxids;
1057
 
        }
1058
 
        ret = xenHypervisorDoV2Sys(handle, &op);
1059
 
 
1060
 
        if (ret == 0) {
1061
 
            if (sys_interface_version < 3)
1062
 
                ret = op.u.getdomaininfolist.num_domains;
1063
 
            else
1064
 
                ret = op.u.getdomaininfolists3.num_domains;
1065
 
        }
1066
 
    } else if (hypervisor_version == 1) {
1067
 
        xen_op_v1 op;
1068
 
 
1069
 
        memset(&op, 0, sizeof(op));
1070
 
        op.cmd = XEN_V1_OP_GETDOMAININFOLIST;
1071
 
        op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
1072
 
        op.u.getdomaininfolist.max_domains = maxids;
1073
 
        op.u.getdomaininfolist.buffer = dominfos->v0;
1074
 
        op.u.getdomaininfolist.num_domains = maxids;
1075
 
        ret = xenHypervisorDoV1Op(handle, &op);
1076
 
        if (ret == 0)
1077
 
            ret = op.u.getdomaininfolist.num_domains;
1078
 
    } else if (hypervisor_version == 0) {
1079
 
        xen_op_v0 op;
1080
 
 
1081
 
        memset(&op, 0, sizeof(op));
1082
 
        op.cmd = XEN_V0_OP_GETDOMAININFOLIST;
1083
 
        op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
1084
 
        op.u.getdomaininfolist.max_domains = maxids;
1085
 
        op.u.getdomaininfolist.buffer = dominfos->v0;
1086
 
        op.u.getdomaininfolist.num_domains = maxids;
1087
 
        ret = xenHypervisorDoV0Op(handle, &op);
1088
 
        if (ret == 0)
1089
 
            ret = op.u.getdomaininfolist.num_domains;
1090
 
    }
1091
 
    if (unlock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
1092
 
                XEN_GETDOMAININFO_SIZE * maxids) < 0) {
1093
 
        virXenError(VIR_ERR_XEN_CALL, " release");
1094
 
        ret = -1;
1095
 
    }
1096
 
    return(ret);
1097
 
}
1098
 
 
1099
 
static int
1100
 
virXen_getdomaininfo(int handle, int first_domain,
1101
 
                     xen_getdomaininfo *dominfo) {
1102
 
    xen_getdomaininfolist dominfos;
1103
 
 
1104
 
    if (hypervisor_version < 2) {
1105
 
        dominfos.v0 = &(dominfo->v0);
1106
 
    } else {
1107
 
        dominfos.v2 = &(dominfo->v2);
1108
 
    }
1109
 
 
1110
 
    return virXen_getdomaininfolist(handle, first_domain, 1, &dominfos);
1111
 
}
1112
 
 
1113
 
 
1114
 
#ifndef PROXY
1115
 
/**
1116
 
 * xenHypervisorGetSchedulerType:
1117
 
 * @domain: pointer to the Xen Hypervisor block
1118
 
 * @nparams:give a number of scheduler parameters.
1119
 
 *
1120
 
 * Do a low level hypercall to get scheduler type
1121
 
 *
1122
 
 * Returns scheduler name or NULL in case of failure
1123
 
 */
1124
 
char *
1125
 
xenHypervisorGetSchedulerType(virDomainPtr domain, int *nparams)
1126
 
{
1127
 
    char *schedulertype = NULL;
1128
 
    xenUnifiedPrivatePtr priv;
1129
 
 
1130
 
    if (domain->conn == NULL) {
1131
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
1132
 
                        "domain or conn is NULL", 0);
1133
 
        return NULL;
1134
 
    }
1135
 
 
1136
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
1137
 
    if (priv->handle < 0) {
1138
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
1139
 
                        "priv->handle invalid", 0);
1140
 
        return NULL;
1141
 
    }
1142
 
    if (domain->id < 0) {
1143
 
        virXenError(VIR_ERR_OPERATION_INVALID,
1144
 
                    "%s", _("domain is not running"));
1145
 
        return NULL;
1146
 
    }
1147
 
 
1148
 
    /*
1149
 
     * Support only dom_interface_version >=5
1150
 
     * (Xen3.1.0 or later)
1151
 
     * TODO: check on Xen 3.0.3
1152
 
     */
1153
 
    if (dom_interface_version < 5) {
1154
 
        virXenErrorFunc(VIR_ERR_NO_XEN, __FUNCTION__,
1155
 
                        "unsupported in dom interface < 5", 0);
1156
 
        return NULL;
1157
 
    }
1158
 
 
1159
 
    if (hypervisor_version > 1) {
1160
 
        xen_op_v2_sys op;
1161
 
        int ret;
1162
 
 
1163
 
        memset(&op, 0, sizeof(op));
1164
 
        op.cmd = XEN_V2_OP_GETSCHEDULERID;
1165
 
        ret = xenHypervisorDoV2Sys(priv->handle, &op);
1166
 
        if (ret < 0)
1167
 
            return(NULL);
1168
 
 
1169
 
        switch (op.u.getschedulerid.sched_id){
1170
 
            case XEN_SCHEDULER_SEDF:
1171
 
                schedulertype = strdup("sedf");
1172
 
                if (schedulertype == NULL)
1173
 
                    virReportOOMError();
1174
 
                if (nparams)
1175
 
                    *nparams = 6;
1176
 
                break;
1177
 
            case XEN_SCHEDULER_CREDIT:
1178
 
                schedulertype = strdup("credit");
1179
 
                if (schedulertype == NULL)
1180
 
                    virReportOOMError();
1181
 
                if (nparams)
1182
 
                    *nparams = 2;
1183
 
                break;
1184
 
            default:
1185
 
                break;
1186
 
        }
1187
 
    }
1188
 
 
1189
 
    return schedulertype;
1190
 
}
1191
 
 
1192
 
static const char *str_weight = "weight";
1193
 
static const char *str_cap = "cap";
1194
 
 
1195
 
/**
1196
 
 * xenHypervisorGetSchedulerParameters:
1197
 
 * @domain: pointer to the Xen Hypervisor block
1198
 
 * @params: pointer to scheduler parameters.
1199
 
 *     This memory area should be allocated before calling.
1200
 
 * @nparams:this parameter should be same as
1201
 
 *     a given number of scheduler parameters.
1202
 
 *     from xenHypervisorGetSchedulerType().
1203
 
 *
1204
 
 * Do a low level hypercall to get scheduler parameters
1205
 
 *
1206
 
 * Returns 0 or -1 in case of failure
1207
 
 */
1208
 
int
1209
 
xenHypervisorGetSchedulerParameters(virDomainPtr domain,
1210
 
                                    virSchedParameterPtr params, int *nparams)
1211
 
{
1212
 
    xenUnifiedPrivatePtr priv;
1213
 
 
1214
 
    if (domain->conn == NULL) {
1215
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
1216
 
                        "domain or conn is NULL", 0);
1217
 
        return -1;
1218
 
    }
1219
 
 
1220
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
1221
 
    if (priv->handle < 0) {
1222
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
1223
 
                        "priv->handle invalid", 0);
1224
 
        return -1;
1225
 
    }
1226
 
    if (domain->id < 0) {
1227
 
        virXenError(VIR_ERR_OPERATION_INVALID,
1228
 
                    "%s", _("domain is not running"));
1229
 
        return -1;
1230
 
    }
1231
 
 
1232
 
    /*
1233
 
     * Support only dom_interface_version >=5
1234
 
     * (Xen3.1.0 or later)
1235
 
     * TODO: check on Xen 3.0.3
1236
 
     */
1237
 
    if (dom_interface_version < 5) {
1238
 
        virXenErrorFunc(VIR_ERR_NO_XEN, __FUNCTION__,
1239
 
                        "unsupported in dom interface < 5", 0);
1240
 
        return -1;
1241
 
    }
1242
 
 
1243
 
    if (hypervisor_version > 1) {
1244
 
        xen_op_v2_sys op_sys;
1245
 
        xen_op_v2_dom op_dom;
1246
 
        int ret;
1247
 
 
1248
 
        memset(&op_sys, 0, sizeof(op_sys));
1249
 
        op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
1250
 
        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
1251
 
        if (ret < 0)
1252
 
            return -1;
1253
 
 
1254
 
        switch (op_sys.u.getschedulerid.sched_id){
1255
 
            case XEN_SCHEDULER_SEDF:
1256
 
                /* TODO: Implement for Xen/SEDF */
1257
 
                TODO
1258
 
                return(-1);
1259
 
            case XEN_SCHEDULER_CREDIT:
1260
 
                if (*nparams < 2)
1261
 
                    return(-1);
1262
 
                memset(&op_dom, 0, sizeof(op_dom));
1263
 
                op_dom.cmd = XEN_V2_OP_SCHEDULER;
1264
 
                op_dom.domain = (domid_t) domain->id;
1265
 
                op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
1266
 
                op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
1267
 
                ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
1268
 
                if (ret < 0)
1269
 
                    return(-1);
1270
 
 
1271
 
                if (virStrcpyStatic(params[0].field, str_weight) == NULL) {
1272
 
                    virXenError(VIR_ERR_INTERNAL_ERROR,
1273
 
                                "Weight %s too big for destination", str_weight);
1274
 
                    return -1;
1275
 
                }
1276
 
                params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
1277
 
                params[0].value.ui = op_dom.u.getschedinfo.u.credit.weight;
1278
 
 
1279
 
                if (virStrcpyStatic(params[1].field, str_cap) == NULL) {
1280
 
                    virXenError(VIR_ERR_INTERNAL_ERROR,
1281
 
                                "Cap %s too big for destination", str_cap);
1282
 
                    return -1;
1283
 
                }
1284
 
                params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT;
1285
 
                params[1].value.ui = op_dom.u.getschedinfo.u.credit.cap;
1286
 
 
1287
 
                *nparams = 2;
1288
 
                break;
1289
 
            default:
1290
 
                virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
1291
 
                        "Unknown scheduler", op_sys.u.getschedulerid.sched_id);
1292
 
                return -1;
1293
 
        }
1294
 
    }
1295
 
 
1296
 
    return 0;
1297
 
}
1298
 
 
1299
 
/**
1300
 
 * xenHypervisorSetSchedulerParameters:
1301
 
 * @domain: pointer to the Xen Hypervisor block
1302
 
 * @nparams:give a number of scheduler setting parameters .
1303
 
 *
1304
 
 * Do a low level hypercall to set scheduler parameters
1305
 
 *
1306
 
 * Returns 0 or -1 in case of failure
1307
 
 */
1308
 
int
1309
 
xenHypervisorSetSchedulerParameters(virDomainPtr domain,
1310
 
                                 virSchedParameterPtr params, int nparams)
1311
 
{
1312
 
    int i;
1313
 
    unsigned int val;
1314
 
    xenUnifiedPrivatePtr priv;
1315
 
    char buf[256];
1316
 
 
1317
 
    if (domain->conn == NULL) {
1318
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
1319
 
                        "domain or conn is NULL", 0);
1320
 
        return -1;
1321
 
    }
1322
 
 
1323
 
    if ((nparams == 0) || (params == NULL)) {
1324
 
        virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
1325
 
                        "Noparameters given", 0);
1326
 
        return(-1);
1327
 
    }
1328
 
 
1329
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
1330
 
    if (priv->handle < 0) {
1331
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
1332
 
                        "priv->handle invalid", 0);
1333
 
        return -1;
1334
 
    }
1335
 
    if (domain->id < 0) {
1336
 
        virXenError(VIR_ERR_OPERATION_INVALID,
1337
 
                    "%s", _("domain is not running"));
1338
 
        return -1;
1339
 
    }
1340
 
 
1341
 
    /*
1342
 
     * Support only dom_interface_version >=5
1343
 
     * (Xen3.1.0 or later)
1344
 
     * TODO: check on Xen 3.0.3
1345
 
     */
1346
 
    if (dom_interface_version < 5) {
1347
 
        virXenErrorFunc(VIR_ERR_NO_XEN, __FUNCTION__,
1348
 
                        "unsupported in dom interface < 5", 0);
1349
 
        return -1;
1350
 
    }
1351
 
 
1352
 
    if (hypervisor_version > 1) {
1353
 
        xen_op_v2_sys op_sys;
1354
 
        xen_op_v2_dom op_dom;
1355
 
        int ret;
1356
 
 
1357
 
        memset(&op_sys, 0, sizeof(op_sys));
1358
 
        op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
1359
 
        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
1360
 
        if (ret == -1) return -1;
1361
 
 
1362
 
        switch (op_sys.u.getschedulerid.sched_id){
1363
 
        case XEN_SCHEDULER_SEDF:
1364
 
            /* TODO: Implement for Xen/SEDF */
1365
 
            TODO
1366
 
            return(-1);
1367
 
        case XEN_SCHEDULER_CREDIT: {
1368
 
            memset(&op_dom, 0, sizeof(op_dom));
1369
 
            op_dom.cmd = XEN_V2_OP_SCHEDULER;
1370
 
            op_dom.domain = (domid_t) domain->id;
1371
 
            op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
1372
 
            op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
1373
 
 
1374
 
            /*
1375
 
             * credit scheduler parameters
1376
 
             * following values do not change the parameters
1377
 
             */
1378
 
            op_dom.u.getschedinfo.u.credit.weight = 0;
1379
 
            op_dom.u.getschedinfo.u.credit.cap    = (uint16_t)~0U;
1380
 
 
1381
 
            for (i = 0; i < nparams; i++) {
1382
 
                memset(&buf, 0, sizeof(buf));
1383
 
                if (STREQ (params[i].field, str_weight) &&
1384
 
                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
1385
 
                    val = params[i].value.ui;
1386
 
                    if ((val < 1) || (val > USHRT_MAX)) {
1387
 
                        snprintf(buf, sizeof(buf), _("Credit scheduler weight parameter (%d) is out of range (1-65535)"), val);
1388
 
                        virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, buf, val);
1389
 
                        return(-1);
1390
 
                    }
1391
 
                    op_dom.u.getschedinfo.u.credit.weight = val;
1392
 
                } else if (STREQ (params[i].field, str_cap) &&
1393
 
                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
1394
 
                    val = params[i].value.ui;
1395
 
                    if (val >= USHRT_MAX) {
1396
 
                        snprintf(buf, sizeof(buf), _("Credit scheduler cap parameter (%d) is out of range (0-65534)"), val);
1397
 
                        virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, buf, val);
1398
 
                        return(-1);
1399
 
                    }
1400
 
                    op_dom.u.getschedinfo.u.credit.cap = val;
1401
 
                } else {
1402
 
                    virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
1403
 
                                    "Credit scheduler accepts 'cap' and 'weight' integer parameters",
1404
 
                                    0);
1405
 
                    return(-1);
1406
 
                }
1407
 
            }
1408
 
 
1409
 
            ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
1410
 
            if (ret < 0)
1411
 
                return -1;
1412
 
            break;
1413
 
        }
1414
 
        default:
1415
 
            virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
1416
 
                        "Unknown scheduler", op_sys.u.getschedulerid.sched_id);
1417
 
            return -1;
1418
 
        }
1419
 
    }
1420
 
 
1421
 
    return 0;
1422
 
}
1423
 
 
1424
 
 
1425
 
int
1426
 
xenHypervisorDomainBlockStats (virDomainPtr dom,
1427
 
                               const char *path,
1428
 
                               struct _virDomainBlockStats *stats)
1429
 
{
1430
 
# ifdef __linux__
1431
 
    xenUnifiedPrivatePtr priv;
1432
 
    int ret;
1433
 
 
1434
 
    priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
1435
 
    xenUnifiedLock(priv);
1436
 
    /* Need to lock because it hits the xenstore handle :-( */
1437
 
    ret = xenLinuxDomainBlockStats (priv, dom, path, stats);
1438
 
    xenUnifiedUnlock(priv);
1439
 
    return ret;
1440
 
# else
1441
 
    virXenErrorFunc(VIR_ERR_NO_SUPPORT, __FUNCTION__,
1442
 
                    "block statistics not supported on this platform",
1443
 
                    dom->id);
1444
 
    return -1;
1445
 
# endif
1446
 
}
1447
 
 
1448
 
/* Paths have the form vif<domid>.<n> (this interface checks that
1449
 
 * <domid> is the real domain ID and returns an error if not).
1450
 
 *
1451
 
 * In future we may allow you to query bridge stats (virbrX or
1452
 
 * xenbrX), but that will probably be through a separate
1453
 
 * virNetwork interface, as yet not decided.
1454
 
 */
1455
 
int
1456
 
xenHypervisorDomainInterfaceStats (virDomainPtr dom,
1457
 
                                   const char *path,
1458
 
                                   struct _virDomainInterfaceStats *stats)
1459
 
{
1460
 
# ifdef __linux__
1461
 
    int rqdomid, device;
1462
 
 
1463
 
    /* Verify that the vif requested is one belonging to the current
1464
 
     * domain.
1465
 
     */
1466
 
    if (sscanf (path, "vif%d.%d", &rqdomid, &device) != 2) {
1467
 
        virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
1468
 
                        "invalid path, should be vif<domid>.<n>.", 0);
1469
 
        return -1;
1470
 
    }
1471
 
    if (rqdomid != dom->id) {
1472
 
        virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
1473
 
                        "invalid path, vif<domid> should match this domain ID", 0);
1474
 
        return -1;
1475
 
    }
1476
 
 
1477
 
    return linuxDomainInterfaceStats(path, stats);
1478
 
# else
1479
 
    virXenErrorFunc(VIR_ERR_NO_SUPPORT, __FUNCTION__,
1480
 
                    "/proc/net/dev: Interface not found", 0);
1481
 
    return -1;
1482
 
# endif
1483
 
}
1484
 
 
1485
 
/**
1486
 
 * virXen_pausedomain:
1487
 
 * @handle: the hypervisor handle
1488
 
 * @id: the domain id
1489
 
 *
1490
 
 * Do a low level hypercall to pause the domain
1491
 
 *
1492
 
 * Returns 0 or -1 in case of failure
1493
 
 */
1494
 
static int
1495
 
virXen_pausedomain(int handle, int id)
1496
 
{
1497
 
    int ret = -1;
1498
 
 
1499
 
    if (hypervisor_version > 1) {
1500
 
        xen_op_v2_dom op;
1501
 
 
1502
 
        memset(&op, 0, sizeof(op));
1503
 
        op.cmd = XEN_V2_OP_PAUSEDOMAIN;
1504
 
        op.domain = (domid_t) id;
1505
 
        ret = xenHypervisorDoV2Dom(handle, &op);
1506
 
    } else if (hypervisor_version == 1) {
1507
 
        xen_op_v1 op;
1508
 
 
1509
 
        memset(&op, 0, sizeof(op));
1510
 
        op.cmd = XEN_V1_OP_PAUSEDOMAIN;
1511
 
        op.u.domain.domain = (domid_t) id;
1512
 
        ret = xenHypervisorDoV1Op(handle, &op);
1513
 
    } else if (hypervisor_version == 0) {
1514
 
        xen_op_v0 op;
1515
 
 
1516
 
        memset(&op, 0, sizeof(op));
1517
 
        op.cmd = XEN_V0_OP_PAUSEDOMAIN;
1518
 
        op.u.domain.domain = (domid_t) id;
1519
 
        ret = xenHypervisorDoV0Op(handle, &op);
1520
 
    }
1521
 
    return(ret);
1522
 
}
1523
 
 
1524
 
/**
1525
 
 * virXen_unpausedomain:
1526
 
 * @handle: the hypervisor handle
1527
 
 * @id: the domain id
1528
 
 *
1529
 
 * Do a low level hypercall to unpause the domain
1530
 
 *
1531
 
 * Returns 0 or -1 in case of failure
1532
 
 */
1533
 
static int
1534
 
virXen_unpausedomain(int handle, int id)
1535
 
{
1536
 
    int ret = -1;
1537
 
 
1538
 
    if (hypervisor_version > 1) {
1539
 
        xen_op_v2_dom op;
1540
 
 
1541
 
        memset(&op, 0, sizeof(op));
1542
 
        op.cmd = XEN_V2_OP_UNPAUSEDOMAIN;
1543
 
        op.domain = (domid_t) id;
1544
 
        ret = xenHypervisorDoV2Dom(handle, &op);
1545
 
    } else if (hypervisor_version == 1) {
1546
 
        xen_op_v1 op;
1547
 
 
1548
 
        memset(&op, 0, sizeof(op));
1549
 
        op.cmd = XEN_V1_OP_UNPAUSEDOMAIN;
1550
 
        op.u.domain.domain = (domid_t) id;
1551
 
        ret = xenHypervisorDoV1Op(handle, &op);
1552
 
    } else if (hypervisor_version == 0) {
1553
 
        xen_op_v0 op;
1554
 
 
1555
 
        memset(&op, 0, sizeof(op));
1556
 
        op.cmd = XEN_V0_OP_UNPAUSEDOMAIN;
1557
 
        op.u.domain.domain = (domid_t) id;
1558
 
        ret = xenHypervisorDoV0Op(handle, &op);
1559
 
    }
1560
 
    return(ret);
1561
 
}
1562
 
 
1563
 
/**
1564
 
 * virXen_destroydomain:
1565
 
 * @handle: the hypervisor handle
1566
 
 * @id: the domain id
1567
 
 *
1568
 
 * Do a low level hypercall to destroy the domain
1569
 
 *
1570
 
 * Returns 0 or -1 in case of failure
1571
 
 */
1572
 
static int
1573
 
virXen_destroydomain(int handle, int id)
1574
 
{
1575
 
    int ret = -1;
1576
 
 
1577
 
    if (hypervisor_version > 1) {
1578
 
        xen_op_v2_dom op;
1579
 
 
1580
 
        memset(&op, 0, sizeof(op));
1581
 
        op.cmd = XEN_V2_OP_DESTROYDOMAIN;
1582
 
        op.domain = (domid_t) id;
1583
 
        ret = xenHypervisorDoV2Dom(handle, &op);
1584
 
    } else if (hypervisor_version == 1) {
1585
 
        xen_op_v1 op;
1586
 
 
1587
 
        memset(&op, 0, sizeof(op));
1588
 
        op.cmd = XEN_V1_OP_DESTROYDOMAIN;
1589
 
        op.u.domain.domain = (domid_t) id;
1590
 
        ret = xenHypervisorDoV1Op(handle, &op);
1591
 
    } else if (hypervisor_version == 0) {
1592
 
        xen_op_v0 op;
1593
 
 
1594
 
        memset(&op, 0, sizeof(op));
1595
 
        op.cmd = XEN_V0_OP_DESTROYDOMAIN;
1596
 
        op.u.domain.domain = (domid_t) id;
1597
 
        ret = xenHypervisorDoV0Op(handle, &op);
1598
 
    }
1599
 
    return(ret);
1600
 
}
1601
 
 
1602
 
/**
1603
 
 * virXen_setmaxmem:
1604
 
 * @handle: the hypervisor handle
1605
 
 * @id: the domain id
1606
 
 * @memory: the amount of memory in kilobytes
1607
 
 *
1608
 
 * Do a low level hypercall to change the max memory amount
1609
 
 *
1610
 
 * Returns 0 or -1 in case of failure
1611
 
 */
1612
 
static int
1613
 
virXen_setmaxmem(int handle, int id, unsigned long memory)
1614
 
{
1615
 
    int ret = -1;
1616
 
 
1617
 
    if (hypervisor_version > 1) {
1618
 
        xen_op_v2_dom op;
1619
 
 
1620
 
        memset(&op, 0, sizeof(op));
1621
 
        op.cmd = XEN_V2_OP_SETMAXMEM;
1622
 
        op.domain = (domid_t) id;
1623
 
        if (dom_interface_version < 5)
1624
 
            op.u.setmaxmem.maxmem = memory;
1625
 
        else
1626
 
            op.u.setmaxmemd5.maxmem = memory;
1627
 
        ret = xenHypervisorDoV2Dom(handle, &op);
1628
 
    } else if (hypervisor_version == 1) {
1629
 
        xen_op_v1 op;
1630
 
 
1631
 
        memset(&op, 0, sizeof(op));
1632
 
        op.cmd = XEN_V1_OP_SETMAXMEM;
1633
 
        op.u.setmaxmem.domain = (domid_t) id;
1634
 
        op.u.setmaxmem.maxmem = memory;
1635
 
        ret = xenHypervisorDoV1Op(handle, &op);
1636
 
    } else if (hypervisor_version == 0) {
1637
 
        xen_op_v0 op;
1638
 
 
1639
 
        memset(&op, 0, sizeof(op));
1640
 
        op.cmd = XEN_V0_OP_SETMAXMEM;
1641
 
        op.u.setmaxmem.domain = (domid_t) id;
1642
 
        op.u.setmaxmem.maxmem = memory;
1643
 
        ret = xenHypervisorDoV0Op(handle, &op);
1644
 
    }
1645
 
    return(ret);
1646
 
}
1647
 
 
1648
 
/**
1649
 
 * virXen_setmaxvcpus:
1650
 
 * @handle: the hypervisor handle
1651
 
 * @id: the domain id
1652
 
 * @vcpus: the numbers of vcpus
1653
 
 *
1654
 
 * Do a low level hypercall to change the max vcpus amount
1655
 
 *
1656
 
 * Returns 0 or -1 in case of failure
1657
 
 */
1658
 
static int
1659
 
virXen_setmaxvcpus(int handle, int id, unsigned int vcpus)
1660
 
{
1661
 
    int ret = -1;
1662
 
 
1663
 
    if (hypervisor_version > 1) {
1664
 
        xen_op_v2_dom op;
1665
 
 
1666
 
        memset(&op, 0, sizeof(op));
1667
 
        op.cmd = XEN_V2_OP_SETMAXVCPU;
1668
 
        op.domain = (domid_t) id;
1669
 
        op.u.setmaxvcpu.maxvcpu = vcpus;
1670
 
        ret = xenHypervisorDoV2Dom(handle, &op);
1671
 
    } else if (hypervisor_version == 1) {
1672
 
        xen_op_v1 op;
1673
 
 
1674
 
        memset(&op, 0, sizeof(op));
1675
 
        op.cmd = XEN_V1_OP_SETMAXVCPU;
1676
 
        op.u.setmaxvcpu.domain = (domid_t) id;
1677
 
        op.u.setmaxvcpu.maxvcpu = vcpus;
1678
 
        ret = xenHypervisorDoV1Op(handle, &op);
1679
 
    } else if (hypervisor_version == 0) {
1680
 
        xen_op_v0 op;
1681
 
 
1682
 
        memset(&op, 0, sizeof(op));
1683
 
        op.cmd = XEN_V0_OP_SETMAXVCPU;
1684
 
        op.u.setmaxvcpu.domain = (domid_t) id;
1685
 
        op.u.setmaxvcpu.maxvcpu = vcpus;
1686
 
        ret = xenHypervisorDoV0Op(handle, &op);
1687
 
    }
1688
 
    return(ret);
1689
 
}
1690
 
 
1691
 
/**
1692
 
 * virXen_setvcpumap:
1693
 
 * @handle: the hypervisor handle
1694
 
 * @id: the domain id
1695
 
 * @vcpu: the vcpu to map
1696
 
 * @cpumap: the bitmap for this vcpu
1697
 
 * @maplen: the size of the bitmap in bytes
1698
 
 *
1699
 
 * Do a low level hypercall to change the pinning for vcpu
1700
 
 *
1701
 
 * Returns 0 or -1 in case of failure
1702
 
 */
1703
 
static int
1704
 
virXen_setvcpumap(int handle, int id, unsigned int vcpu,
1705
 
                  unsigned char * cpumap, int maplen)
1706
 
{
1707
 
    int ret = -1;
1708
 
    unsigned char *new = NULL;
1709
 
    unsigned char *bitmap = NULL;
1710
 
    uint32_t nr_cpus;
1711
 
 
1712
 
    if (hypervisor_version > 1) {
1713
 
        xen_op_v2_dom op;
1714
 
 
1715
 
        if (lock_pages(cpumap, maplen) < 0) {
1716
 
            virXenError(VIR_ERR_XEN_CALL, " locking");
1717
 
            return (-1);
1718
 
        }
1719
 
        memset(&op, 0, sizeof(op));
1720
 
        op.cmd = XEN_V2_OP_SETVCPUMAP;
1721
 
        op.domain = (domid_t) id;
1722
 
 
1723
 
        /* The allocated memory to cpumap must be 'sizeof(uint64_t)' byte *
1724
 
         * for Xen, and also nr_cpus must be 'sizeof(uint64_t) * 8'       */
1725
 
        if (maplen < 8) {
1726
 
            if (VIR_ALLOC_N(new, sizeof(uint64_t)) < 0) {
1727
 
                virReportOOMError();
1728
 
                return (-1);
1729
 
            }
1730
 
            memcpy(new, cpumap, maplen);
1731
 
            bitmap = new;
1732
 
            nr_cpus = sizeof(uint64_t) * 8;
1733
 
        } else {
1734
 
            bitmap = cpumap;
1735
 
            nr_cpus = maplen * 8;
1736
 
        }
1737
 
 
1738
 
        if (dom_interface_version < 5) {
1739
 
            op.u.setvcpumap.vcpu = vcpu;
1740
 
            op.u.setvcpumap.cpumap.bitmap = bitmap;
1741
 
            op.u.setvcpumap.cpumap.nr_cpus = nr_cpus;
1742
 
        } else {
1743
 
            op.u.setvcpumapd5.vcpu = vcpu;
1744
 
            op.u.setvcpumapd5.cpumap.bitmap.v = bitmap;
1745
 
            op.u.setvcpumapd5.cpumap.nr_cpus = nr_cpus;
1746
 
        }
1747
 
        ret = xenHypervisorDoV2Dom(handle, &op);
1748
 
        VIR_FREE(new);
1749
 
 
1750
 
        if (unlock_pages(cpumap, maplen) < 0) {
1751
 
            virXenError(VIR_ERR_XEN_CALL, " release");
1752
 
            ret = -1;
1753
 
        }
1754
 
    } else {
1755
 
        cpumap_t xen_cpumap; /* limited to 64 CPUs in old hypervisors */
1756
 
        uint64_t *pm = &xen_cpumap;
1757
 
        int j;
1758
 
 
1759
 
        if ((maplen > (int)sizeof(cpumap_t)) || (sizeof(cpumap_t) & 7))
1760
 
            return (-1);
1761
 
 
1762
 
        memset(pm, 0, sizeof(cpumap_t));
1763
 
        for (j = 0; j < maplen; j++)
1764
 
            *(pm + (j / 8)) |= cpumap[j] << (8 * (j & 7));
1765
 
 
1766
 
        if (hypervisor_version == 1) {
1767
 
            xen_op_v1 op;
1768
 
 
1769
 
            memset(&op, 0, sizeof(op));
1770
 
            op.cmd = XEN_V1_OP_SETVCPUMAP;
1771
 
            op.u.setvcpumap.domain = (domid_t) id;
1772
 
            op.u.setvcpumap.vcpu = vcpu;
1773
 
            op.u.setvcpumap.cpumap = xen_cpumap;
1774
 
            ret = xenHypervisorDoV1Op(handle, &op);
1775
 
        } else if (hypervisor_version == 0) {
1776
 
            xen_op_v0 op;
1777
 
 
1778
 
            memset(&op, 0, sizeof(op));
1779
 
            op.cmd = XEN_V0_OP_SETVCPUMAP;
1780
 
            op.u.setvcpumap.domain = (domid_t) id;
1781
 
            op.u.setvcpumap.vcpu = vcpu;
1782
 
            op.u.setvcpumap.cpumap = xen_cpumap;
1783
 
            ret = xenHypervisorDoV0Op(handle, &op);
1784
 
        }
1785
 
    }
1786
 
    return(ret);
1787
 
}
1788
 
#endif /* !PROXY*/
1789
 
 
1790
 
/**
1791
 
 * virXen_getvcpusinfo:
1792
 
 * @handle: the hypervisor handle
1793
 
 * @id: the domain id
1794
 
 * @vcpu: the vcpu to map
1795
 
 * @cpumap: the bitmap for this vcpu
1796
 
 * @maplen: the size of the bitmap in bytes
1797
 
 *
1798
 
 * Do a low level hypercall to change the pinning for vcpu
1799
 
 *
1800
 
 * Returns 0 or -1 in case of failure
1801
 
 */
1802
 
static int
1803
 
virXen_getvcpusinfo(int handle, int id, unsigned int vcpu, virVcpuInfoPtr ipt,
1804
 
                    unsigned char *cpumap, int maplen)
1805
 
{
1806
 
    int ret = -1;
1807
 
 
1808
 
    if (hypervisor_version > 1) {
1809
 
        xen_op_v2_dom op;
1810
 
 
1811
 
        memset(&op, 0, sizeof(op));
1812
 
        op.cmd = XEN_V2_OP_GETVCPUINFO;
1813
 
        op.domain = (domid_t) id;
1814
 
        if (dom_interface_version < 5)
1815
 
            op.u.getvcpuinfo.vcpu = (uint16_t) vcpu;
1816
 
        else
1817
 
            op.u.getvcpuinfod5.vcpu = (uint16_t) vcpu;
1818
 
        ret = xenHypervisorDoV2Dom(handle, &op);
1819
 
 
1820
 
        if (ret < 0)
1821
 
            return(-1);
1822
 
        ipt->number = vcpu;
1823
 
        if (dom_interface_version < 5) {
1824
 
            if (op.u.getvcpuinfo.online) {
1825
 
                if (op.u.getvcpuinfo.running)
1826
 
                    ipt->state = VIR_VCPU_RUNNING;
1827
 
                if (op.u.getvcpuinfo.blocked)
1828
 
                    ipt->state = VIR_VCPU_BLOCKED;
1829
 
            } else
1830
 
                ipt->state = VIR_VCPU_OFFLINE;
1831
 
 
1832
 
            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
1833
 
            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
1834
 
        } else {
1835
 
            if (op.u.getvcpuinfod5.online) {
1836
 
                if (op.u.getvcpuinfod5.running)
1837
 
                    ipt->state = VIR_VCPU_RUNNING;
1838
 
                if (op.u.getvcpuinfod5.blocked)
1839
 
                    ipt->state = VIR_VCPU_BLOCKED;
1840
 
            } else
1841
 
                ipt->state = VIR_VCPU_OFFLINE;
1842
 
 
1843
 
            ipt->cpuTime = op.u.getvcpuinfod5.cpu_time;
1844
 
            ipt->cpu = op.u.getvcpuinfod5.online ? (int)op.u.getvcpuinfod5.cpu : -1;
1845
 
        }
1846
 
        if ((cpumap != NULL) && (maplen > 0)) {
1847
 
            if (lock_pages(cpumap, maplen) < 0) {
1848
 
                virXenError(VIR_ERR_XEN_CALL, " locking");
1849
 
                return (-1);
1850
 
            }
1851
 
            memset(cpumap, 0, maplen);
1852
 
            memset(&op, 0, sizeof(op));
1853
 
            op.cmd = XEN_V2_OP_GETVCPUMAP;
1854
 
            op.domain = (domid_t) id;
1855
 
            if (dom_interface_version < 5) {
1856
 
                op.u.getvcpumap.vcpu = vcpu;
1857
 
                op.u.getvcpumap.cpumap.bitmap = cpumap;
1858
 
                op.u.getvcpumap.cpumap.nr_cpus = maplen * 8;
1859
 
            } else {
1860
 
                op.u.getvcpumapd5.vcpu = vcpu;
1861
 
                op.u.getvcpumapd5.cpumap.bitmap.v = cpumap;
1862
 
                op.u.getvcpumapd5.cpumap.nr_cpus = maplen * 8;
1863
 
            }
1864
 
            ret = xenHypervisorDoV2Dom(handle, &op);
1865
 
            if (unlock_pages(cpumap, maplen) < 0) {
1866
 
                virXenError(VIR_ERR_XEN_CALL, " release");
1867
 
                ret = -1;
1868
 
            }
1869
 
        }
1870
 
    } else {
1871
 
        int mapl = maplen;
1872
 
        int cpu;
1873
 
 
1874
 
        if (maplen > (int)sizeof(cpumap_t))
1875
 
            mapl = (int)sizeof(cpumap_t);
1876
 
 
1877
 
        if (hypervisor_version == 1) {
1878
 
            xen_op_v1 op;
1879
 
 
1880
 
            memset(&op, 0, sizeof(op));
1881
 
            op.cmd = XEN_V1_OP_GETVCPUINFO;
1882
 
            op.u.getvcpuinfo.domain = (domid_t) id;
1883
 
            op.u.getvcpuinfo.vcpu = vcpu;
1884
 
            ret = xenHypervisorDoV1Op(handle, &op);
1885
 
            if (ret < 0)
1886
 
                return(-1);
1887
 
            ipt->number = vcpu;
1888
 
            if (op.u.getvcpuinfo.online) {
1889
 
                if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
1890
 
                if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
1891
 
            }
1892
 
            else ipt->state = VIR_VCPU_OFFLINE;
1893
 
            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
1894
 
            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
1895
 
            if ((cpumap != NULL) && (maplen > 0)) {
1896
 
                for (cpu = 0; cpu < (mapl * 8); cpu++) {
1897
 
                    if (op.u.getvcpuinfo.cpumap & ((uint64_t)1<<cpu))
1898
 
                        VIR_USE_CPU(cpumap, cpu);
1899
 
                }
1900
 
            }
1901
 
        } else if (hypervisor_version == 0) {
1902
 
            xen_op_v1 op;
1903
 
 
1904
 
            memset(&op, 0, sizeof(op));
1905
 
            op.cmd = XEN_V0_OP_GETVCPUINFO;
1906
 
            op.u.getvcpuinfo.domain = (domid_t) id;
1907
 
            op.u.getvcpuinfo.vcpu = vcpu;
1908
 
            ret = xenHypervisorDoV0Op(handle, &op);
1909
 
            if (ret < 0)
1910
 
                return(-1);
1911
 
            ipt->number = vcpu;
1912
 
            if (op.u.getvcpuinfo.online) {
1913
 
                if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
1914
 
                if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
1915
 
            }
1916
 
            else ipt->state = VIR_VCPU_OFFLINE;
1917
 
            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
1918
 
            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
1919
 
            if ((cpumap != NULL) && (maplen > 0)) {
1920
 
                for (cpu = 0; cpu < (mapl * 8); cpu++) {
1921
 
                    if (op.u.getvcpuinfo.cpumap & ((uint64_t)1<<cpu))
1922
 
                        VIR_USE_CPU(cpumap, cpu);
1923
 
                }
1924
 
            }
1925
 
        }
1926
 
    }
1927
 
    return(ret);
1928
 
}
1929
 
 
1930
 
/**
1931
 
 * xenHypervisorInit:
1932
 
 *
1933
 
 * Initialize the hypervisor layer. Try to detect the kind of interface
1934
 
 * used i.e. pre or post changeset 10277
1935
 
 */
1936
 
int
1937
 
xenHypervisorInit(void)
1938
 
{
1939
 
    int fd, ret, cmd, errcode;
1940
 
    hypercall_t hc;
1941
 
    v0_hypercall_t v0_hc;
1942
 
    xen_getdomaininfo info;
1943
 
    virVcpuInfoPtr ipt = NULL;
1944
 
 
1945
 
    if (initialized) {
1946
 
        if (hypervisor_version == -1)
1947
 
            return (-1);
1948
 
        return(0);
1949
 
    }
1950
 
    initialized = 1;
1951
 
    in_init = 1;
1952
 
 
1953
 
    /* Compile regular expressions used by xenHypervisorGetCapabilities.
1954
 
     * Note that errors here are really internal errors since these
1955
 
     * regexps should never fail to compile.
1956
 
     */
1957
 
    errcode = regcomp (&flags_hvm_rec, flags_hvm_re, REG_EXTENDED);
1958
 
    if (errcode != 0) {
1959
 
        char error[100];
1960
 
        regerror (errcode, &flags_hvm_rec, error, sizeof error);
1961
 
        regfree (&flags_hvm_rec);
1962
 
        virXenError(VIR_ERR_INTERNAL_ERROR, "%s", error);
1963
 
        in_init = 0;
1964
 
        return -1;
1965
 
    }
1966
 
    errcode = regcomp (&flags_pae_rec, flags_pae_re, REG_EXTENDED);
1967
 
    if (errcode != 0) {
1968
 
        char error[100];
1969
 
        regerror (errcode, &flags_pae_rec, error, sizeof error);
1970
 
        regfree (&flags_pae_rec);
1971
 
        regfree (&flags_hvm_rec);
1972
 
        virXenError(VIR_ERR_INTERNAL_ERROR, "%s", error);
1973
 
        in_init = 0;
1974
 
        return -1;
1975
 
    }
1976
 
    errcode = regcomp (&xen_cap_rec, xen_cap_re, REG_EXTENDED);
1977
 
    if (errcode != 0) {
1978
 
        char error[100];
1979
 
        regerror (errcode, &xen_cap_rec, error, sizeof error);
1980
 
        regfree (&xen_cap_rec);
1981
 
        regfree (&flags_pae_rec);
1982
 
        regfree (&flags_hvm_rec);
1983
 
        virXenError(VIR_ERR_INTERNAL_ERROR, "%s", error);
1984
 
        in_init = 0;
1985
 
        return -1;
1986
 
    }
1987
 
 
1988
 
    /* Xen hypervisor version detection begins. */
1989
 
    ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
1990
 
    if (ret < 0) {
1991
 
        hypervisor_version = -1;
1992
 
        return(-1);
1993
 
    }
1994
 
    fd = ret;
1995
 
 
1996
 
    /*
1997
 
     * The size of the hypervisor call block changed July 2006
1998
 
     * this detect if we are using the new or old hypercall_t structure
1999
 
     */
2000
 
    hc.op = __HYPERVISOR_xen_version;
2001
 
    hc.arg[0] = (unsigned long) XENVER_version;
2002
 
    hc.arg[1] = 0;
2003
 
 
2004
 
    cmd = IOCTL_PRIVCMD_HYPERCALL;
2005
 
    ret = ioctl(fd, cmd, (unsigned long) &hc);
2006
 
 
2007
 
    if ((ret != -1) && (ret != 0)) {
2008
 
        DEBUG("Using new hypervisor call: %X", ret);
2009
 
        hv_version = ret;
2010
 
        xen_ioctl_hypercall_cmd = cmd;
2011
 
        goto detect_v2;
2012
 
    }
2013
 
 
2014
 
#ifndef __sun
2015
 
    /*
2016
 
     * check if the old hypercall are actually working
2017
 
     */
2018
 
    v0_hc.op = __HYPERVISOR_xen_version;
2019
 
    v0_hc.arg[0] = (unsigned long) XENVER_version;
2020
 
    v0_hc.arg[1] = 0;
2021
 
    cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t));
2022
 
    ret = ioctl(fd, cmd, (unsigned long) &v0_hc);
2023
 
    if ((ret != -1) && (ret != 0)) {
2024
 
        DEBUG("Using old hypervisor call: %X", ret);
2025
 
        hv_version = ret;
2026
 
        xen_ioctl_hypercall_cmd = cmd;
2027
 
        hypervisor_version = 0;
2028
 
        goto done;
2029
 
    }
2030
 
#endif
2031
 
 
2032
 
    /*
2033
 
     * we failed to make any hypercall
2034
 
     */
2035
 
 
2036
 
    hypervisor_version = -1;
2037
 
    virXenError(VIR_ERR_XEN_CALL, " ioctl %lu",
2038
 
                (unsigned long) IOCTL_PRIVCMD_HYPERCALL);
2039
 
    close(fd);
2040
 
    in_init = 0;
2041
 
    return(-1);
2042
 
 
2043
 
 detect_v2:
2044
 
    /*
2045
 
     * The hypercalls were refactored into 3 different section in August 2006
2046
 
     * Try to detect if we are running a version post 3.0.2 with the new ones
2047
 
     * or the old ones
2048
 
     */
2049
 
    hypervisor_version = 2;
2050
 
 
2051
 
    if (VIR_ALLOC(ipt) < 0) {
2052
 
        virReportOOMError();
2053
 
        return(-1);
2054
 
    }
2055
 
    /* Currently consider RHEL5.0 Fedora7, xen-3.1, and xen-unstable */
2056
 
    sys_interface_version = 2; /* XEN_SYSCTL_INTERFACE_VERSION */
2057
 
    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
2058
 
        /* RHEL 5.0 */
2059
 
        dom_interface_version = 3; /* XEN_DOMCTL_INTERFACE_VERSION */
2060
 
        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
2061
 
            DEBUG0("Using hypervisor call v2, sys ver2 dom ver3");
2062
 
            goto done;
2063
 
        }
2064
 
        /* Fedora 7 */
2065
 
        dom_interface_version = 4; /* XEN_DOMCTL_INTERFACE_VERSION */
2066
 
        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
2067
 
            DEBUG0("Using hypervisor call v2, sys ver2 dom ver4");
2068
 
            goto done;
2069
 
        }
2070
 
    }
2071
 
 
2072
 
    sys_interface_version = 3; /* XEN_SYSCTL_INTERFACE_VERSION */
2073
 
    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
2074
 
        /* xen-3.1 */
2075
 
        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
2076
 
        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
2077
 
            DEBUG0("Using hypervisor call v2, sys ver3 dom ver5");
2078
 
            goto done;
2079
 
        }
2080
 
    }
2081
 
 
2082
 
    sys_interface_version = 4; /* XEN_SYSCTL_INTERFACE_VERSION */
2083
 
    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
2084
 
        /* Fedora 8 */
2085
 
        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
2086
 
        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
2087
 
            DEBUG0("Using hypervisor call v2, sys ver4 dom ver5");
2088
 
            goto done;
2089
 
        }
2090
 
    }
2091
 
 
2092
 
    sys_interface_version = 6; /* XEN_SYSCTL_INTERFACE_VERSION */
2093
 
    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
2094
 
        /* Xen 3.2, Fedora 9 */
2095
 
        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
2096
 
        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
2097
 
            DEBUG0("Using hypervisor call v2, sys ver6 dom ver5");
2098
 
            goto done;
2099
 
        }
2100
 
    }
2101
 
 
2102
 
    /* Xen 4.0 */
2103
 
    sys_interface_version = 7; /* XEN_SYSCTL_INTERFACE_VERSION */
2104
 
    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
2105
 
        dom_interface_version = 6; /* XEN_DOMCTL_INTERFACE_VERSION */
2106
 
        DEBUG0("Using hypervisor call v2, sys ver7 dom ver6");
2107
 
        goto done;
2108
 
    }
2109
 
 
2110
 
    hypervisor_version = 1;
2111
 
    sys_interface_version = -1;
2112
 
    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
2113
 
        DEBUG0("Using hypervisor call v1");
2114
 
        goto done;
2115
 
    }
2116
 
 
2117
 
    /*
2118
 
     * we failed to make the getdomaininfolist hypercall
2119
 
     */
2120
 
 
2121
 
    DEBUG0("Failed to find any Xen hypervisor method");
2122
 
    hypervisor_version = -1;
2123
 
    virXenError(VIR_ERR_XEN_CALL, " ioctl %lu",
2124
 
                (unsigned long)IOCTL_PRIVCMD_HYPERCALL);
2125
 
    close(fd);
2126
 
    in_init = 0;
2127
 
    VIR_FREE(ipt);
2128
 
    return(-1);
2129
 
 
2130
 
 done:
2131
 
    close(fd);
2132
 
    in_init = 0;
2133
 
    VIR_FREE(ipt);
2134
 
    return(0);
2135
 
}
2136
 
 
2137
 
/**
2138
 
 * xenHypervisorOpen:
2139
 
 * @conn: pointer to the connection block
2140
 
 * @name: URL for the target, NULL for local
2141
 
 * @flags: combination of virDrvOpenFlag(s)
2142
 
 *
2143
 
 * Connects to the Xen hypervisor.
2144
 
 *
2145
 
 * Returns 0 or -1 in case of error.
2146
 
 */
2147
 
virDrvOpenStatus
2148
 
xenHypervisorOpen(virConnectPtr conn,
2149
 
                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
2150
 
                  int flags ATTRIBUTE_UNUSED)
2151
 
{
2152
 
    int ret;
2153
 
    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
2154
 
 
2155
 
    if (initialized == 0)
2156
 
        if (xenHypervisorInit() == -1)
2157
 
            return -1;
2158
 
 
2159
 
    priv->handle = -1;
2160
 
 
2161
 
    ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
2162
 
    if (ret < 0) {
2163
 
        virXenError(VIR_ERR_NO_XEN, "%s", XEN_HYPERVISOR_SOCKET);
2164
 
        return (-1);
2165
 
    }
2166
 
 
2167
 
    priv->handle = ret;
2168
 
 
2169
 
    return(0);
2170
 
}
2171
 
 
2172
 
/**
2173
 
 * xenHypervisorClose:
2174
 
 * @conn: pointer to the connection block
2175
 
 *
2176
 
 * Close the connection to the Xen hypervisor.
2177
 
 *
2178
 
 * Returns 0 in case of success or -1 in case of error.
2179
 
 */
2180
 
int
2181
 
xenHypervisorClose(virConnectPtr conn)
2182
 
{
2183
 
    int ret;
2184
 
    xenUnifiedPrivatePtr priv;
2185
 
 
2186
 
    if (conn == NULL)
2187
 
        return (-1);
2188
 
 
2189
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
2190
 
 
2191
 
    if (priv->handle < 0)
2192
 
        return -1;
2193
 
 
2194
 
    ret = close(priv->handle);
2195
 
    if (ret < 0)
2196
 
        return (-1);
2197
 
 
2198
 
    return (0);
2199
 
}
2200
 
 
2201
 
 
2202
 
/**
2203
 
 * xenHypervisorGetVersion:
2204
 
 * @conn: pointer to the connection block
2205
 
 * @hvVer: where to store the version
2206
 
 *
2207
 
 * Call the hypervisor to extracts his own internal API version
2208
 
 *
2209
 
 * Returns 0 in case of success, -1 in case of error
2210
 
 */
2211
 
int
2212
 
xenHypervisorGetVersion(virConnectPtr conn, unsigned long *hvVer)
2213
 
{
2214
 
    xenUnifiedPrivatePtr priv;
2215
 
 
2216
 
    if (conn == NULL)
2217
 
        return -1;
2218
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
2219
 
    if (priv->handle < 0 || hvVer == NULL)
2220
 
        return (-1);
2221
 
    *hvVer = (hv_version >> 16) * 1000000 + (hv_version & 0xFFFF) * 1000;
2222
 
    return(0);
2223
 
}
2224
 
 
2225
 
struct guest_arch {
2226
 
    const char *model;
2227
 
    int bits;
2228
 
    int hvm;
2229
 
    int pae;
2230
 
    int nonpae;
2231
 
    int ia64_be;
2232
 
};
2233
 
 
2234
 
 
2235
 
static virCapsPtr
2236
 
xenHypervisorBuildCapabilities(virConnectPtr conn,
2237
 
                               const char *hostmachine,
2238
 
                               int host_pae,
2239
 
                               const char *hvm_type,
2240
 
                               struct guest_arch *guest_archs,
2241
 
                               int nr_guest_archs) {
2242
 
    virCapsPtr caps;
2243
 
    int i;
2244
 
    int hv_major = hv_version >> 16;
2245
 
    int hv_minor = hv_version & 0xFFFF;
2246
 
 
2247
 
    if ((caps = virCapabilitiesNew(hostmachine, 1, 1)) == NULL)
2248
 
        goto no_memory;
2249
 
 
2250
 
    virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x16, 0x3e });
2251
 
 
2252
 
    if (hvm_type && STRNEQ(hvm_type, "") &&
2253
 
        virCapabilitiesAddHostFeature(caps, hvm_type) < 0)
2254
 
        goto no_memory;
2255
 
    if (host_pae &&
2256
 
        virCapabilitiesAddHostFeature(caps, "pae") < 0)
2257
 
        goto no_memory;
2258
 
 
2259
 
 
2260
 
    if (virCapabilitiesAddHostMigrateTransport(caps,
2261
 
                                               "xenmigr") < 0)
2262
 
        goto no_memory;
2263
 
 
2264
 
 
2265
 
    if (sys_interface_version >= SYS_IFACE_MIN_VERS_NUMA) {
2266
 
        if (xenDaemonNodeGetTopology(conn, caps) != 0) {
2267
 
            virCapabilitiesFree(caps);
2268
 
            return NULL;
2269
 
        }
2270
 
    }
2271
 
 
2272
 
    for (i = 0; i < nr_guest_archs; ++i) {
2273
 
        virCapsGuestPtr guest;
2274
 
        char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
2275
 
        virCapsGuestMachinePtr *machines;
2276
 
 
2277
 
        if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
2278
 
            goto no_memory;
2279
 
 
2280
 
        if ((guest = virCapabilitiesAddGuest(caps,
2281
 
                                             guest_archs[i].hvm ? "hvm" : "xen",
2282
 
                                             guest_archs[i].model,
2283
 
                                             guest_archs[i].bits,
2284
 
                                             (STREQ(hostmachine, "x86_64") ?
2285
 
                                              "/usr/lib64/xen/bin/qemu-dm" :
2286
 
                                              "/usr/lib/xen/bin/qemu-dm"),
2287
 
                                             (guest_archs[i].hvm ?
2288
 
                                              "/usr/lib/xen/boot/hvmloader" :
2289
 
                                              NULL),
2290
 
                                             1,
2291
 
                                             machines)) == NULL) {
2292
 
            virCapabilitiesFreeMachines(machines, 1);
2293
 
            goto no_memory;
2294
 
        }
2295
 
        machines = NULL;
2296
 
 
2297
 
        if (virCapabilitiesAddGuestDomain(guest,
2298
 
                                          "xen",
2299
 
                                          NULL,
2300
 
                                          NULL,
2301
 
                                          0,
2302
 
                                          NULL) == NULL)
2303
 
            goto no_memory;
2304
 
 
2305
 
        if (guest_archs[i].pae &&
2306
 
            virCapabilitiesAddGuestFeature(guest,
2307
 
                                           "pae",
2308
 
                                           1,
2309
 
                                           0) == NULL)
2310
 
            goto no_memory;
2311
 
 
2312
 
        if (guest_archs[i].nonpae &&
2313
 
            virCapabilitiesAddGuestFeature(guest,
2314
 
                                           "nonpae",
2315
 
                                           1,
2316
 
                                           0) == NULL)
2317
 
            goto no_memory;
2318
 
 
2319
 
        if (guest_archs[i].ia64_be &&
2320
 
            virCapabilitiesAddGuestFeature(guest,
2321
 
                                           "ia64_be",
2322
 
                                           1,
2323
 
                                           0) == NULL)
2324
 
            goto no_memory;
2325
 
 
2326
 
        if (guest_archs[i].hvm) {
2327
 
            if (virCapabilitiesAddGuestFeature(guest,
2328
 
                                               "acpi",
2329
 
                                               1, 1) == NULL)
2330
 
                goto no_memory;
2331
 
 
2332
 
            // In Xen 3.1.0, APIC is always on and can't be toggled
2333
 
            if (virCapabilitiesAddGuestFeature(guest,
2334
 
                                               "apic",
2335
 
                                               1,
2336
 
                                               (hv_major > 3 &&
2337
 
                                                hv_minor > 0 ?
2338
 
                                                0 : 1)) == NULL)
2339
 
                goto no_memory;
2340
 
        }
2341
 
    }
2342
 
 
2343
 
    caps->defaultConsoleTargetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
2344
 
 
2345
 
    return caps;
2346
 
 
2347
 
 no_memory:
2348
 
    virCapabilitiesFree(caps);
2349
 
    return NULL;
2350
 
}
2351
 
 
2352
 
#ifdef __sun
2353
 
 
2354
 
static int
2355
 
get_cpu_flags(virConnectPtr conn, const char **hvm, int *pae, int *longmode)
2356
 
{
2357
 
    struct {
2358
 
        uint32_t r_eax, r_ebx, r_ecx, r_edx;
2359
 
    } regs;
2360
 
 
2361
 
    char tmpbuf[20];
2362
 
    int ret = 0;
2363
 
    int fd;
2364
 
 
2365
 
    /* returns -1, errno 22 if in 32-bit mode */
2366
 
    *longmode = (sysinfo(SI_ARCHITECTURE_64, tmpbuf, sizeof(tmpbuf)) != -1);
2367
 
 
2368
 
    if ((fd = open("/dev/cpu/self/cpuid", O_RDONLY)) == -1 ||
2369
 
        pread(fd, &regs, sizeof(regs), 0) != sizeof(regs)) {
2370
 
        virReportSystemError(errno, "%s", _("could not read CPU flags"));
2371
 
        goto out;
2372
 
    }
2373
 
 
2374
 
    *pae = 0;
2375
 
    *hvm = "";
2376
 
 
2377
 
    if (STREQLEN((const char *)&regs.r_ebx, "AuthcAMDenti", 12)) {
2378
 
        if (pread(fd, &regs, sizeof (regs), 0x80000001) == sizeof (regs)) {
2379
 
            /* Read secure virtual machine bit (bit 2 of ECX feature ID) */
2380
 
            if ((regs.r_ecx >> 2) & 1) {
2381
 
                *hvm = "svm";
2382
 
            }
2383
 
            if ((regs.r_edx >> 6) & 1)
2384
 
                *pae = 1;
2385
 
        }
2386
 
    } else if (STREQLEN((const char *)&regs.r_ebx, "GenuntelineI", 12)) {
2387
 
        if (pread(fd, &regs, sizeof (regs), 0x00000001) == sizeof (regs)) {
2388
 
            /* Read VMXE feature bit (bit 5 of ECX feature ID) */
2389
 
            if ((regs.r_ecx >> 5) & 1)
2390
 
                *hvm = "vmx";
2391
 
            if ((regs.r_edx >> 6) & 1)
2392
 
                *pae = 1;
2393
 
        }
2394
 
    }
2395
 
 
2396
 
    ret = 1;
2397
 
 
2398
 
out:
2399
 
    if (fd != -1)
2400
 
        close(fd);
2401
 
    return ret;
2402
 
}
2403
 
 
2404
 
static virCapsPtr
2405
 
xenHypervisorMakeCapabilitiesSunOS(virConnectPtr conn)
2406
 
{
2407
 
    struct guest_arch guest_arches[32];
2408
 
    int i = 0;
2409
 
    virCapsPtr caps = NULL;
2410
 
    struct utsname utsname;
2411
 
    int pae, longmode;
2412
 
    const char *hvm;
2413
 
 
2414
 
    if (!get_cpu_flags(conn, &hvm, &pae, &longmode))
2415
 
        return NULL;
2416
 
 
2417
 
    /* Really, this never fails - look at the man-page. */
2418
 
    uname (&utsname);
2419
 
 
2420
 
    guest_arches[i].model = "i686";
2421
 
    guest_arches[i].bits = 32;
2422
 
    guest_arches[i].hvm = 0;
2423
 
    guest_arches[i].pae = pae;
2424
 
    guest_arches[i].nonpae = !pae;
2425
 
    guest_arches[i].ia64_be = 0;
2426
 
    i++;
2427
 
 
2428
 
    if (longmode) {
2429
 
        guest_arches[i].model = "x86_64";
2430
 
        guest_arches[i].bits = 64;
2431
 
        guest_arches[i].hvm = 0;
2432
 
        guest_arches[i].pae = 0;
2433
 
        guest_arches[i].nonpae = 0;
2434
 
        guest_arches[i].ia64_be = 0;
2435
 
        i++;
2436
 
    }
2437
 
 
2438
 
    if (hvm[0] != '\0') {
2439
 
        guest_arches[i].model = "i686";
2440
 
        guest_arches[i].bits = 32;
2441
 
        guest_arches[i].hvm = 1;
2442
 
        guest_arches[i].pae = pae;
2443
 
        guest_arches[i].nonpae = 1;
2444
 
        guest_arches[i].ia64_be = 0;
2445
 
        i++;
2446
 
 
2447
 
        if (longmode) {
2448
 
            guest_arches[i].model = "x86_64";
2449
 
            guest_arches[i].bits = 64;
2450
 
            guest_arches[i].hvm = 1;
2451
 
            guest_arches[i].pae = 0;
2452
 
            guest_arches[i].nonpae = 0;
2453
 
            guest_arches[i].ia64_be = 0;
2454
 
            i++;
2455
 
        }
2456
 
    }
2457
 
 
2458
 
    if ((caps = xenHypervisorBuildCapabilities(conn,
2459
 
                                               utsname.machine,
2460
 
                                               pae, hvm,
2461
 
                                               guest_arches, i)) == NULL)
2462
 
        virReportOOMError();
2463
 
 
2464
 
    return caps;
2465
 
}
2466
 
 
2467
 
#endif /* __sun */
2468
 
 
2469
 
/**
2470
 
 * xenHypervisorMakeCapabilitiesInternal:
2471
 
 * @conn: pointer to the connection block
2472
 
 * @cpuinfo: file handle containing /proc/cpuinfo data, or NULL
2473
 
 * @capabilities: file handle containing /sys/hypervisor/properties/capabilities data, or NULL
2474
 
 *
2475
 
 * Return the capabilities of this hypervisor.
2476
 
 */
2477
 
virCapsPtr
2478
 
xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
2479
 
                                      const char *hostmachine,
2480
 
                                      FILE *cpuinfo, FILE *capabilities)
2481
 
{
2482
 
    char line[1024], *str, *token;
2483
 
    regmatch_t subs[4];
2484
 
    char *saveptr = NULL;
2485
 
    int i;
2486
 
 
2487
 
    char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */
2488
 
    int host_pae = 0;
2489
 
    struct guest_arch guest_archs[32];
2490
 
    int nr_guest_archs = 0;
2491
 
    virCapsPtr caps = NULL;
2492
 
 
2493
 
    memset(guest_archs, 0, sizeof(guest_archs));
2494
 
 
2495
 
    /* /proc/cpuinfo: flags: Intel calls HVM "vmx", AMD calls it "svm".
2496
 
     * It's not clear if this will work on IA64, let alone other
2497
 
     * architectures and non-Linux. (XXX)
2498
 
     */
2499
 
    if (cpuinfo) {
2500
 
        while (fgets (line, sizeof line, cpuinfo)) {
2501
 
            if (regexec (&flags_hvm_rec, line, sizeof(subs)/sizeof(regmatch_t), subs, 0) == 0
2502
 
                && subs[0].rm_so != -1) {
2503
 
                if (virStrncpy(hvm_type,
2504
 
                               &line[subs[1].rm_so],
2505
 
                               subs[1].rm_eo-subs[1].rm_so,
2506
 
                               sizeof(hvm_type)) == NULL)
2507
 
                    return NULL;
2508
 
            } else if (regexec (&flags_pae_rec, line, 0, NULL, 0) == 0)
2509
 
                host_pae = 1;
2510
 
        }
2511
 
    }
2512
 
 
2513
 
    /* Most of the useful info is in /sys/hypervisor/properties/capabilities
2514
 
     * which is documented in the code in xen-unstable.hg/xen/arch/.../setup.c.
2515
 
     *
2516
 
     * It is a space-separated list of supported guest architectures.
2517
 
     *
2518
 
     * For x86:
2519
 
     *    TYP-VER-ARCH[p]
2520
 
     *    ^   ^   ^    ^
2521
 
     *    |   |   |    +-- PAE supported
2522
 
     *    |   |   +------- x86_32 or x86_64
2523
 
     *    |   +----------- the version of Xen, eg. "3.0"
2524
 
     *    +--------------- "xen" or "hvm" for para or full virt respectively
2525
 
     *
2526
 
     * For PPC this file appears to be always empty (?)
2527
 
     *
2528
 
     * For IA64:
2529
 
     *    TYP-VER-ARCH[be]
2530
 
     *    ^   ^   ^    ^
2531
 
     *    |   |   |    +-- Big-endian supported
2532
 
     *    |   |   +------- always "ia64"
2533
 
     *    |   +----------- the version of Xen, eg. "3.0"
2534
 
     *    +--------------- "xen" or "hvm" for para or full virt respectively
2535
 
     */
2536
 
 
2537
 
    /* Expecting one line in this file - ignore any more. */
2538
 
    if ((capabilities) && (fgets (line, sizeof line, capabilities))) {
2539
 
        /* Split the line into tokens.  strtok_r is OK here because we "own"
2540
 
         * this buffer.  Parse out the features from each token.
2541
 
         */
2542
 
        for (str = line, nr_guest_archs = 0;
2543
 
             nr_guest_archs < sizeof guest_archs / sizeof guest_archs[0]
2544
 
                 && (token = strtok_r (str, " ", &saveptr)) != NULL;
2545
 
             str = NULL) {
2546
 
 
2547
 
            if (regexec (&xen_cap_rec, token, sizeof subs / sizeof subs[0],
2548
 
                         subs, 0) == 0) {
2549
 
                int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
2550
 
                const char *model;
2551
 
                int bits, pae = 0, nonpae = 0, ia64_be = 0;
2552
 
 
2553
 
                if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
2554
 
                    model = "i686";
2555
 
                    bits = 32;
2556
 
                    if (subs[3].rm_so != -1 &&
2557
 
                        STRPREFIX(&token[subs[3].rm_so], "p"))
2558
 
                        pae = 1;
2559
 
                    else
2560
 
                        nonpae = 1;
2561
 
                }
2562
 
                else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
2563
 
                    model = "x86_64";
2564
 
                    bits = 64;
2565
 
                }
2566
 
                else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
2567
 
                    model = "ia64";
2568
 
                    bits = 64;
2569
 
                    if (subs[3].rm_so != -1 &&
2570
 
                        STRPREFIX(&token[subs[3].rm_so], "be"))
2571
 
                        ia64_be = 1;
2572
 
                }
2573
 
                else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
2574
 
                    model = "ppc64";
2575
 
                    bits = 64;
2576
 
                } else {
2577
 
                    /* XXX surely no other Xen archs exist  */
2578
 
                    continue;
2579
 
                }
2580
 
 
2581
 
                /* Search for existing matching (model,hvm) tuple */
2582
 
                for (i = 0 ; i < nr_guest_archs ; i++) {
2583
 
                    if (STREQ(guest_archs[i].model, model) &&
2584
 
                        guest_archs[i].hvm == hvm) {
2585
 
                        break;
2586
 
                    }
2587
 
                }
2588
 
 
2589
 
                /* Too many arch flavours - highly unlikely ! */
2590
 
                if (i >= ARRAY_CARDINALITY(guest_archs))
2591
 
                    continue;
2592
 
                /* Didn't find a match, so create a new one */
2593
 
                if (i == nr_guest_archs)
2594
 
                    nr_guest_archs++;
2595
 
 
2596
 
                guest_archs[i].model = model;
2597
 
                guest_archs[i].bits = bits;
2598
 
                guest_archs[i].hvm = hvm;
2599
 
 
2600
 
                /* Careful not to overwrite a previous positive
2601
 
                   setting with a negative one here - some archs
2602
 
                   can do both pae & non-pae, but Xen reports
2603
 
                   separately capabilities so we're merging archs */
2604
 
                if (pae)
2605
 
                    guest_archs[i].pae = pae;
2606
 
                if (nonpae)
2607
 
                    guest_archs[i].nonpae = nonpae;
2608
 
                if (ia64_be)
2609
 
                    guest_archs[i].ia64_be = ia64_be;
2610
 
            }
2611
 
        }
2612
 
    }
2613
 
 
2614
 
    if ((caps = xenHypervisorBuildCapabilities(conn,
2615
 
                                               hostmachine,
2616
 
                                               host_pae,
2617
 
                                               hvm_type,
2618
 
                                               guest_archs,
2619
 
                                               nr_guest_archs)) == NULL)
2620
 
        goto no_memory;
2621
 
 
2622
 
    return caps;
2623
 
 
2624
 
 no_memory:
2625
 
    virReportOOMError();
2626
 
    virCapabilitiesFree(caps);
2627
 
    return NULL;
2628
 
}
2629
 
 
2630
 
/**
2631
 
 * xenHypervisorMakeCapabilities:
2632
 
 *
2633
 
 * Return the capabilities of this hypervisor.
2634
 
 */
2635
 
virCapsPtr
2636
 
xenHypervisorMakeCapabilities(virConnectPtr conn)
2637
 
{
2638
 
#ifdef __sun
2639
 
    return xenHypervisorMakeCapabilitiesSunOS(conn);
2640
 
#else
2641
 
    virCapsPtr caps;
2642
 
    FILE *cpuinfo, *capabilities;
2643
 
    struct utsname utsname;
2644
 
 
2645
 
    /* Really, this never fails - look at the man-page. */
2646
 
    uname (&utsname);
2647
 
 
2648
 
    cpuinfo = fopen ("/proc/cpuinfo", "r");
2649
 
    if (cpuinfo == NULL) {
2650
 
        if (errno != ENOENT) {
2651
 
            virReportSystemError(errno,
2652
 
                                 _("cannot read file %s"),
2653
 
                                 "/proc/cpuinfo");
2654
 
            return NULL;
2655
 
        }
2656
 
    }
2657
 
 
2658
 
    capabilities = fopen ("/sys/hypervisor/properties/capabilities", "r");
2659
 
    if (capabilities == NULL) {
2660
 
        if (errno != ENOENT) {
2661
 
            fclose(cpuinfo);
2662
 
            virReportSystemError(errno,
2663
 
                                 _("cannot read file %s"),
2664
 
                                 "/sys/hypervisor/properties/capabilities");
2665
 
            return NULL;
2666
 
        }
2667
 
    }
2668
 
 
2669
 
    caps = xenHypervisorMakeCapabilitiesInternal(conn,
2670
 
                                                 utsname.machine,
2671
 
                                                 cpuinfo,
2672
 
                                                 capabilities);
2673
 
 
2674
 
    if (cpuinfo)
2675
 
        fclose(cpuinfo);
2676
 
    if (capabilities)
2677
 
        fclose(capabilities);
2678
 
 
2679
 
    return caps;
2680
 
#endif /* __sun */
2681
 
}
2682
 
 
2683
 
 
2684
 
 
2685
 
/**
2686
 
 * xenHypervisorGetCapabilities:
2687
 
 * @conn: pointer to the connection block
2688
 
 *
2689
 
 * Return the capabilities of this hypervisor.
2690
 
 */
2691
 
char *
2692
 
xenHypervisorGetCapabilities (virConnectPtr conn)
2693
 
{
2694
 
    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
2695
 
    char *xml;
2696
 
 
2697
 
    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
2698
 
        virReportOOMError();
2699
 
        return NULL;
2700
 
    }
2701
 
 
2702
 
    return xml;
2703
 
}
2704
 
 
2705
 
 
2706
 
/**
2707
 
 * xenHypervisorNumOfDomains:
2708
 
 * @conn: pointer to the connection block
2709
 
 *
2710
 
 * Provides the number of active domains.
2711
 
 *
2712
 
 * Returns the number of domain found or -1 in case of error
2713
 
 */
2714
 
int
2715
 
xenHypervisorNumOfDomains(virConnectPtr conn)
2716
 
{
2717
 
    xen_getdomaininfolist dominfos;
2718
 
    int ret, nbids;
2719
 
    static int last_maxids = 2;
2720
 
    int maxids = last_maxids;
2721
 
    xenUnifiedPrivatePtr priv;
2722
 
 
2723
 
    if (conn == NULL)
2724
 
        return -1;
2725
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
2726
 
    if (priv->handle < 0)
2727
 
        return (-1);
2728
 
 
2729
 
 retry:
2730
 
    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
2731
 
        virReportOOMError();
2732
 
        return(-1);
2733
 
    }
2734
 
 
2735
 
    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
2736
 
 
2737
 
    ret = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
2738
 
 
2739
 
    XEN_GETDOMAININFOLIST_FREE(dominfos);
2740
 
 
2741
 
    if (ret < 0)
2742
 
        return (-1);
2743
 
 
2744
 
    nbids = ret;
2745
 
    /* Can't possibly have more than 65,000 concurrent guests
2746
 
     * so limit how many times we try, to avoid increasing
2747
 
     * without bound & thus allocating all of system memory !
2748
 
     * XXX I'll regret this comment in a few years time ;-)
2749
 
     */
2750
 
    if (nbids == maxids) {
2751
 
        if (maxids < 65000) {
2752
 
            last_maxids *= 2;
2753
 
            maxids *= 2;
2754
 
            goto retry;
2755
 
        }
2756
 
        nbids = -1;
2757
 
    }
2758
 
    if ((nbids < 0) || (nbids > maxids))
2759
 
        return(-1);
2760
 
    return(nbids);
2761
 
}
2762
 
 
2763
 
/**
2764
 
 * xenHypervisorListDomains:
2765
 
 * @conn: pointer to the connection block
2766
 
 * @ids: array to collect the list of IDs of active domains
2767
 
 * @maxids: size of @ids
2768
 
 *
2769
 
 * Collect the list of active domains, and store their ID in @maxids
2770
 
 *
2771
 
 * Returns the number of domain found or -1 in case of error
2772
 
 */
2773
 
int
2774
 
xenHypervisorListDomains(virConnectPtr conn, int *ids, int maxids)
2775
 
{
2776
 
    xen_getdomaininfolist dominfos;
2777
 
    int ret, nbids, i;
2778
 
    xenUnifiedPrivatePtr priv;
2779
 
 
2780
 
    if (conn == NULL)
2781
 
        return -1;
2782
 
 
2783
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
2784
 
    if (priv->handle < 0 ||
2785
 
        (ids == NULL) || (maxids < 0))
2786
 
        return (-1);
2787
 
 
2788
 
    if (maxids == 0)
2789
 
        return(0);
2790
 
 
2791
 
    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
2792
 
        virReportOOMError();
2793
 
        return(-1);
2794
 
    }
2795
 
 
2796
 
    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
2797
 
    memset(ids, 0, maxids * sizeof(int));
2798
 
 
2799
 
    ret = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
2800
 
 
2801
 
    if (ret < 0) {
2802
 
        XEN_GETDOMAININFOLIST_FREE(dominfos);
2803
 
        return (-1);
2804
 
    }
2805
 
 
2806
 
    nbids = ret;
2807
 
    if ((nbids < 0) || (nbids > maxids)) {
2808
 
        XEN_GETDOMAININFOLIST_FREE(dominfos);
2809
 
        return(-1);
2810
 
    }
2811
 
 
2812
 
    for (i = 0;i < nbids;i++) {
2813
 
        ids[i] = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i);
2814
 
    }
2815
 
 
2816
 
    XEN_GETDOMAININFOLIST_FREE(dominfos);
2817
 
    return (nbids);
2818
 
}
2819
 
 
2820
 
 
2821
 
#ifndef PROXY
2822
 
char *
2823
 
xenHypervisorDomainGetOSType (virDomainPtr dom)
2824
 
{
2825
 
    xenUnifiedPrivatePtr priv;
2826
 
    xen_getdomaininfo dominfo;
2827
 
    char *ostype = NULL;
2828
 
 
2829
 
    priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
2830
 
    if (priv->handle < 0) {
2831
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
2832
 
                        _("domain shut off or invalid"), 0);
2833
 
        return (NULL);
2834
 
    }
2835
 
 
2836
 
    /* HV's earlier than 3.1.0 don't include the HVM flags in guests status*/
2837
 
    if (hypervisor_version < 2 ||
2838
 
        dom_interface_version < 4) {
2839
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
2840
 
                        _("unsupported in dom interface < 4"), 0);
2841
 
        return (NULL);
2842
 
    }
2843
 
 
2844
 
    XEN_GETDOMAININFO_CLEAR(dominfo);
2845
 
 
2846
 
    if (virXen_getdomaininfo(priv->handle, dom->id, &dominfo) < 0) {
2847
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
2848
 
                        _("cannot get domain details"), 0);
2849
 
        return (NULL);
2850
 
    }
2851
 
 
2852
 
    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != dom->id) {
2853
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
2854
 
                        _("cannot get domain details"), 0);
2855
 
        return (NULL);
2856
 
    }
2857
 
 
2858
 
    if (XEN_GETDOMAININFO_FLAGS(dominfo) & DOMFLAGS_HVM)
2859
 
        ostype = strdup("hvm");
2860
 
    else
2861
 
        ostype = strdup("linux");
2862
 
 
2863
 
    if (ostype == NULL)
2864
 
        virReportOOMError();
2865
 
 
2866
 
    return ostype;
2867
 
}
2868
 
 
2869
 
int
2870
 
xenHypervisorHasDomain(virConnectPtr conn,
2871
 
                       int id)
2872
 
{
2873
 
    xenUnifiedPrivatePtr priv;
2874
 
    xen_getdomaininfo dominfo;
2875
 
 
2876
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
2877
 
    if (priv->handle < 0)
2878
 
        return 0;
2879
 
 
2880
 
    XEN_GETDOMAININFO_CLEAR(dominfo);
2881
 
 
2882
 
    if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0)
2883
 
        return 0;
2884
 
 
2885
 
    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
2886
 
        return 0;
2887
 
 
2888
 
    return 1;
2889
 
}
2890
 
 
2891
 
virDomainPtr
2892
 
xenHypervisorLookupDomainByID(virConnectPtr conn,
2893
 
                              int id)
2894
 
{
2895
 
    xenUnifiedPrivatePtr priv;
2896
 
    xen_getdomaininfo dominfo;
2897
 
    virDomainPtr ret;
2898
 
    char *name;
2899
 
 
2900
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
2901
 
    if (priv->handle < 0)
2902
 
        return (NULL);
2903
 
 
2904
 
    XEN_GETDOMAININFO_CLEAR(dominfo);
2905
 
 
2906
 
    if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0)
2907
 
        return (NULL);
2908
 
 
2909
 
    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
2910
 
        return (NULL);
2911
 
 
2912
 
    xenUnifiedLock(priv);
2913
 
    name = xenStoreDomainGetName(conn, id);
2914
 
    xenUnifiedUnlock(priv);
2915
 
    if (!name)
2916
 
        return (NULL);
2917
 
 
2918
 
    ret = virGetDomain(conn, name, XEN_GETDOMAININFO_UUID(dominfo));
2919
 
    if (ret)
2920
 
        ret->id = id;
2921
 
    VIR_FREE(name);
2922
 
    return ret;
2923
 
}
2924
 
 
2925
 
 
2926
 
virDomainPtr
2927
 
xenHypervisorLookupDomainByUUID(virConnectPtr conn,
2928
 
                                const unsigned char *uuid)
2929
 
{
2930
 
    xen_getdomaininfolist dominfos;
2931
 
    xenUnifiedPrivatePtr priv;
2932
 
    virDomainPtr ret;
2933
 
    char *name;
2934
 
    int maxids = 100, nids, i, id;
2935
 
 
2936
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
2937
 
    if (priv->handle < 0)
2938
 
        return (NULL);
2939
 
 
2940
 
 retry:
2941
 
    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
2942
 
        virReportOOMError();
2943
 
        return(NULL);
2944
 
    }
2945
 
 
2946
 
    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
2947
 
 
2948
 
    nids = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
2949
 
 
2950
 
    if (nids < 0) {
2951
 
        XEN_GETDOMAININFOLIST_FREE(dominfos);
2952
 
        return (NULL);
2953
 
    }
2954
 
 
2955
 
    /* Can't possibly have more than 65,000 concurrent guests
2956
 
     * so limit how many times we try, to avoid increasing
2957
 
     * without bound & thus allocating all of system memory !
2958
 
     * XXX I'll regret this comment in a few years time ;-)
2959
 
     */
2960
 
    if (nids == maxids) {
2961
 
        XEN_GETDOMAININFOLIST_FREE(dominfos);
2962
 
        if (maxids < 65000) {
2963
 
            maxids *= 2;
2964
 
            goto retry;
2965
 
        }
2966
 
        return (NULL);
2967
 
    }
2968
 
 
2969
 
    id = -1;
2970
 
    for (i = 0 ; i < nids ; i++) {
2971
 
        if (memcmp(XEN_GETDOMAININFOLIST_UUID(dominfos, i), uuid, VIR_UUID_BUFLEN) == 0) {
2972
 
            id = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i);
2973
 
            break;
2974
 
        }
2975
 
    }
2976
 
    XEN_GETDOMAININFOLIST_FREE(dominfos);
2977
 
 
2978
 
    if (id == -1)
2979
 
        return (NULL);
2980
 
 
2981
 
    xenUnifiedLock(priv);
2982
 
    name = xenStoreDomainGetName(conn, id);
2983
 
    xenUnifiedUnlock(priv);
2984
 
    if (!name)
2985
 
        return (NULL);
2986
 
 
2987
 
    ret = virGetDomain(conn, name, uuid);
2988
 
    if (ret)
2989
 
        ret->id = id;
2990
 
    VIR_FREE(name);
2991
 
    return ret;
2992
 
}
2993
 
#endif
2994
 
 
2995
 
/**
2996
 
 * xenHypervisorGetMaxVcpus:
2997
 
 *
2998
 
 * Returns the maximum of CPU defined by Xen.
2999
 
 */
3000
 
int
3001
 
xenHypervisorGetMaxVcpus(virConnectPtr conn,
3002
 
                         const char *type ATTRIBUTE_UNUSED)
3003
 
{
3004
 
    xenUnifiedPrivatePtr priv;
3005
 
 
3006
 
    if (conn == NULL)
3007
 
        return -1;
3008
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
3009
 
    if (priv->handle < 0)
3010
 
        return (-1);
3011
 
 
3012
 
    return MAX_VIRT_CPUS;
3013
 
}
3014
 
 
3015
 
/**
3016
 
 * xenHypervisorGetDomMaxMemory:
3017
 
 * @conn: connection data
3018
 
 * @id: domain id
3019
 
 *
3020
 
 * Retrieve the maximum amount of physical memory allocated to a
3021
 
 * domain.
3022
 
 *
3023
 
 * Returns the memory size in kilobytes or 0 in case of error.
3024
 
 */
3025
 
unsigned long
3026
 
xenHypervisorGetDomMaxMemory(virConnectPtr conn, int id)
3027
 
{
3028
 
    xenUnifiedPrivatePtr priv;
3029
 
    xen_getdomaininfo dominfo;
3030
 
    int ret;
3031
 
 
3032
 
    if (conn == NULL)
3033
 
        return 0;
3034
 
 
3035
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
3036
 
    if (priv->handle < 0)
3037
 
        return 0;
3038
 
 
3039
 
    if (kb_per_pages == 0) {
3040
 
        kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
3041
 
        if (kb_per_pages <= 0)
3042
 
            kb_per_pages = 4;
3043
 
    }
3044
 
 
3045
 
    XEN_GETDOMAININFO_CLEAR(dominfo);
3046
 
 
3047
 
    ret = virXen_getdomaininfo(priv->handle, id, &dominfo);
3048
 
 
3049
 
    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != id))
3050
 
        return (0);
3051
 
 
3052
 
    return((unsigned long) XEN_GETDOMAININFO_MAX_PAGES(dominfo) * kb_per_pages);
3053
 
}
3054
 
 
3055
 
#ifndef PROXY
3056
 
/**
3057
 
 * xenHypervisorGetMaxMemory:
3058
 
 * @domain: a domain object or NULL
3059
 
 *
3060
 
 * Retrieve the maximum amount of physical memory allocated to a
3061
 
 * domain. If domain is NULL, then this get the amount of memory reserved
3062
 
 * to Domain0 i.e. the domain where the application runs.
3063
 
 *
3064
 
 * Returns the memory size in kilobytes or 0 in case of error.
3065
 
 */
3066
 
static unsigned long ATTRIBUTE_NONNULL (1)
3067
 
xenHypervisorGetMaxMemory(virDomainPtr domain)
3068
 
{
3069
 
    xenUnifiedPrivatePtr priv;
3070
 
 
3071
 
    if (domain->conn == NULL)
3072
 
        return 0;
3073
 
 
3074
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3075
 
    if (priv->handle < 0 || domain->id < 0)
3076
 
        return (0);
3077
 
 
3078
 
    return(xenHypervisorGetDomMaxMemory(domain->conn, domain->id));
3079
 
}
3080
 
#endif
3081
 
 
3082
 
/**
3083
 
 * xenHypervisorGetDomInfo:
3084
 
 * @conn: connection data
3085
 
 * @id: the domain ID
3086
 
 * @info: the place where information should be stored
3087
 
 *
3088
 
 * Do an hypervisor call to get the related set of domain information.
3089
 
 *
3090
 
 * Returns 0 in case of success, -1 in case of error.
3091
 
 */
3092
 
int
3093
 
xenHypervisorGetDomInfo(virConnectPtr conn, int id, virDomainInfoPtr info)
3094
 
{
3095
 
    xenUnifiedPrivatePtr priv;
3096
 
    xen_getdomaininfo dominfo;
3097
 
    int ret;
3098
 
    uint32_t domain_flags, domain_state, domain_shutdown_cause;
3099
 
 
3100
 
    if (kb_per_pages == 0) {
3101
 
        kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
3102
 
        if (kb_per_pages <= 0)
3103
 
            kb_per_pages = 4;
3104
 
    }
3105
 
 
3106
 
    if (conn == NULL)
3107
 
        return -1;
3108
 
 
3109
 
    priv = (xenUnifiedPrivatePtr) conn->privateData;
3110
 
    if (priv->handle < 0 || info == NULL)
3111
 
        return (-1);
3112
 
 
3113
 
    memset(info, 0, sizeof(virDomainInfo));
3114
 
    XEN_GETDOMAININFO_CLEAR(dominfo);
3115
 
 
3116
 
    ret = virXen_getdomaininfo(priv->handle, id, &dominfo);
3117
 
 
3118
 
    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != id))
3119
 
        return (-1);
3120
 
 
3121
 
    domain_flags = XEN_GETDOMAININFO_FLAGS(dominfo);
3122
 
    domain_flags &= ~DOMFLAGS_HVM; /* Mask out HVM flags */
3123
 
    domain_state = domain_flags & 0xFF; /* Mask out high bits */
3124
 
    switch (domain_state) {
3125
 
        case DOMFLAGS_DYING:
3126
 
            info->state = VIR_DOMAIN_SHUTDOWN;
3127
 
            break;
3128
 
        case DOMFLAGS_SHUTDOWN:
3129
 
            /* The domain is shutdown.  Determine the cause. */
3130
 
            domain_shutdown_cause = domain_flags >> DOMFLAGS_SHUTDOWNSHIFT;
3131
 
            switch (domain_shutdown_cause) {
3132
 
                case SHUTDOWN_crash:
3133
 
                    info->state = VIR_DOMAIN_CRASHED;
3134
 
                    break;
3135
 
                default:
3136
 
                    info->state = VIR_DOMAIN_SHUTOFF;
3137
 
            }
3138
 
            break;
3139
 
        case DOMFLAGS_PAUSED:
3140
 
            info->state = VIR_DOMAIN_PAUSED;
3141
 
            break;
3142
 
        case DOMFLAGS_BLOCKED:
3143
 
            info->state = VIR_DOMAIN_BLOCKED;
3144
 
            break;
3145
 
        case DOMFLAGS_RUNNING:
3146
 
            info->state = VIR_DOMAIN_RUNNING;
3147
 
            break;
3148
 
        default:
3149
 
            info->state = VIR_DOMAIN_NOSTATE;
3150
 
    }
3151
 
 
3152
 
    /*
3153
 
     * the API brings back the cpu time in nanoseconds,
3154
 
     * convert to microseconds, same thing convert to
3155
 
     * kilobytes from page counts
3156
 
     */
3157
 
    info->cpuTime = XEN_GETDOMAININFO_CPUTIME(dominfo);
3158
 
    info->memory = XEN_GETDOMAININFO_TOT_PAGES(dominfo) * kb_per_pages;
3159
 
    info->maxMem = XEN_GETDOMAININFO_MAX_PAGES(dominfo);
3160
 
    if(info->maxMem != UINT_MAX)
3161
 
        info->maxMem *= kb_per_pages;
3162
 
    info->nrVirtCpu = XEN_GETDOMAININFO_CPUCOUNT(dominfo);
3163
 
    return (0);
3164
 
}
3165
 
 
3166
 
/**
3167
 
 * xenHypervisorGetDomainInfo:
3168
 
 * @domain: pointer to the domain block
3169
 
 * @info: the place where information should be stored
3170
 
 *
3171
 
 * Do an hypervisor call to get the related set of domain information.
3172
 
 *
3173
 
 * Returns 0 in case of success, -1 in case of error.
3174
 
 */
3175
 
int
3176
 
xenHypervisorGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info)
3177
 
{
3178
 
    xenUnifiedPrivatePtr priv;
3179
 
 
3180
 
    if (domain->conn == NULL)
3181
 
        return -1;
3182
 
 
3183
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3184
 
    if (priv->handle < 0 || info == NULL ||
3185
 
        (domain->id < 0))
3186
 
        return (-1);
3187
 
 
3188
 
    return(xenHypervisorGetDomInfo(domain->conn, domain->id, info));
3189
 
 
3190
 
}
3191
 
 
3192
 
#ifndef PROXY
3193
 
/**
3194
 
 * xenHypervisorNodeGetCellsFreeMemory:
3195
 
 * @conn: pointer to the hypervisor connection
3196
 
 * @freeMems: pointer to the array of unsigned long long
3197
 
 * @startCell: index of first cell to return freeMems info on.
3198
 
 * @maxCells: Maximum number of cells for which freeMems information can
3199
 
 *            be returned.
3200
 
 *
3201
 
 * This call returns the amount of free memory in one or more NUMA cells.
3202
 
 * The @freeMems array must be allocated by the caller and will be filled
3203
 
 * with the amount of free memory in kilobytes for each cell requested,
3204
 
 * starting with startCell (in freeMems[0]), up to either
3205
 
 * (startCell + maxCells), or the number of additional cells in the node,
3206
 
 * whichever is smaller.
3207
 
 *
3208
 
 * Returns the number of entries filled in freeMems, or -1 in case of error.
3209
 
 */
3210
 
int
3211
 
xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
3212
 
                                    int startCell, int maxCells)
3213
 
{
3214
 
    xen_op_v2_sys op_sys;
3215
 
    int i, j, ret;
3216
 
    xenUnifiedPrivatePtr priv;
3217
 
 
3218
 
    if (conn == NULL) {
3219
 
        virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
3220
 
                        "invalid argument", 0);
3221
 
        return -1;
3222
 
    }
3223
 
 
3224
 
    priv = conn->privateData;
3225
 
 
3226
 
    if (priv->nbNodeCells < 0) {
3227
 
        virXenErrorFunc(VIR_ERR_XEN_CALL, __FUNCTION__,
3228
 
                        "cannot determine actual number of cells",0);
3229
 
        return(-1);
3230
 
    }
3231
 
 
3232
 
    if ((maxCells < 1) || (startCell >= priv->nbNodeCells)) {
3233
 
        virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
3234
 
                        "invalid argument", 0);
3235
 
        return -1;
3236
 
    }
3237
 
 
3238
 
    /*
3239
 
     * Support only sys_interface_version >=4
3240
 
     */
3241
 
    if (sys_interface_version < SYS_IFACE_MIN_VERS_NUMA) {
3242
 
        virXenErrorFunc(VIR_ERR_XEN_CALL, __FUNCTION__,
3243
 
                        "unsupported in sys interface < 4", 0);
3244
 
        return -1;
3245
 
    }
3246
 
 
3247
 
    if (priv->handle < 0) {
3248
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
3249
 
                        "priv->handle invalid", 0);
3250
 
        return -1;
3251
 
    }
3252
 
 
3253
 
    memset(&op_sys, 0, sizeof(op_sys));
3254
 
    op_sys.cmd = XEN_V2_OP_GETAVAILHEAP;
3255
 
 
3256
 
    for (i = startCell, j = 0;(i < priv->nbNodeCells) && (j < maxCells);i++,j++) {
3257
 
        if (sys_interface_version >= 5)
3258
 
            op_sys.u.availheap5.node = i;
3259
 
        else
3260
 
            op_sys.u.availheap.node = i;
3261
 
        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
3262
 
        if (ret < 0) {
3263
 
            return(-1);
3264
 
        }
3265
 
        if (sys_interface_version >= 5)
3266
 
            freeMems[j] = op_sys.u.availheap5.avail_bytes;
3267
 
        else
3268
 
            freeMems[j] = op_sys.u.availheap.avail_bytes;
3269
 
    }
3270
 
    return (j);
3271
 
}
3272
 
 
3273
 
 
3274
 
/**
3275
 
 * xenHypervisorPauseDomain:
3276
 
 * @domain: pointer to the domain block
3277
 
 *
3278
 
 * Do an hypervisor call to pause the given domain
3279
 
 *
3280
 
 * Returns 0 in case of success, -1 in case of error.
3281
 
 */
3282
 
int
3283
 
xenHypervisorPauseDomain(virDomainPtr domain)
3284
 
{
3285
 
    int ret;
3286
 
    xenUnifiedPrivatePtr priv;
3287
 
 
3288
 
    if (domain->conn == NULL)
3289
 
        return -1;
3290
 
 
3291
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3292
 
    if (priv->handle < 0 || domain->id < 0)
3293
 
        return (-1);
3294
 
 
3295
 
    ret = virXen_pausedomain(priv->handle, domain->id);
3296
 
    if (ret < 0)
3297
 
        return (-1);
3298
 
    return (0);
3299
 
}
3300
 
 
3301
 
/**
3302
 
 * xenHypervisorResumeDomain:
3303
 
 * @domain: pointer to the domain block
3304
 
 *
3305
 
 * Do an hypervisor call to resume the given domain
3306
 
 *
3307
 
 * Returns 0 in case of success, -1 in case of error.
3308
 
 */
3309
 
int
3310
 
xenHypervisorResumeDomain(virDomainPtr domain)
3311
 
{
3312
 
    int ret;
3313
 
    xenUnifiedPrivatePtr priv;
3314
 
 
3315
 
    if (domain->conn == NULL)
3316
 
        return -1;
3317
 
 
3318
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3319
 
    if (priv->handle < 0 || domain->id < 0)
3320
 
        return (-1);
3321
 
 
3322
 
    ret = virXen_unpausedomain(priv->handle, domain->id);
3323
 
    if (ret < 0)
3324
 
        return (-1);
3325
 
    return (0);
3326
 
}
3327
 
 
3328
 
/**
3329
 
 * xenHypervisorDestroyDomain:
3330
 
 * @domain: pointer to the domain block
3331
 
 *
3332
 
 * Do an hypervisor call to destroy the given domain
3333
 
 *
3334
 
 * Returns 0 in case of success, -1 in case of error.
3335
 
 */
3336
 
int
3337
 
xenHypervisorDestroyDomain(virDomainPtr domain)
3338
 
{
3339
 
    int ret;
3340
 
    xenUnifiedPrivatePtr priv;
3341
 
 
3342
 
    if (domain->conn == NULL)
3343
 
        return -1;
3344
 
 
3345
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3346
 
    if (priv->handle < 0 || domain->id < 0)
3347
 
        return (-1);
3348
 
 
3349
 
    ret = virXen_destroydomain(priv->handle, domain->id);
3350
 
    if (ret < 0)
3351
 
        return (-1);
3352
 
    return (0);
3353
 
}
3354
 
 
3355
 
/**
3356
 
 * xenHypervisorSetMaxMemory:
3357
 
 * @domain: pointer to the domain block
3358
 
 * @memory: the max memory size in kilobytes.
3359
 
 *
3360
 
 * Do an hypervisor call to change the maximum amount of memory used
3361
 
 *
3362
 
 * Returns 0 in case of success, -1 in case of error.
3363
 
 */
3364
 
int
3365
 
xenHypervisorSetMaxMemory(virDomainPtr domain, unsigned long memory)
3366
 
{
3367
 
    int ret;
3368
 
    xenUnifiedPrivatePtr priv;
3369
 
 
3370
 
    if (domain->conn == NULL)
3371
 
        return -1;
3372
 
 
3373
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3374
 
    if (priv->handle < 0 || domain->id < 0)
3375
 
        return (-1);
3376
 
 
3377
 
    ret = virXen_setmaxmem(priv->handle, domain->id, memory);
3378
 
    if (ret < 0)
3379
 
        return (-1);
3380
 
    return (0);
3381
 
}
3382
 
#endif /* PROXY */
3383
 
 
3384
 
#ifndef PROXY
3385
 
/**
3386
 
 * xenHypervisorSetVcpus:
3387
 
 * @domain: pointer to domain object
3388
 
 * @nvcpus: the new number of virtual CPUs for this domain
3389
 
 *
3390
 
 * Dynamically change the number of virtual CPUs used by the domain.
3391
 
 *
3392
 
 * Returns 0 in case of success, -1 in case of failure.
3393
 
 */
3394
 
 
3395
 
int
3396
 
xenHypervisorSetVcpus(virDomainPtr domain, unsigned int nvcpus)
3397
 
{
3398
 
    int ret;
3399
 
    xenUnifiedPrivatePtr priv;
3400
 
 
3401
 
    if (domain->conn == NULL)
3402
 
        return -1;
3403
 
 
3404
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3405
 
    if (priv->handle < 0 || domain->id < 0 || nvcpus < 1)
3406
 
        return (-1);
3407
 
 
3408
 
    ret = virXen_setmaxvcpus(priv->handle, domain->id, nvcpus);
3409
 
    if (ret < 0)
3410
 
        return (-1);
3411
 
    return (0);
3412
 
}
3413
 
 
3414
 
/**
3415
 
 * xenHypervisorPinVcpu:
3416
 
 * @domain: pointer to domain object
3417
 
 * @vcpu: virtual CPU number
3418
 
 * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
3419
 
 * @maplen: length of cpumap in bytes
3420
 
 *
3421
 
 * Dynamically change the real CPUs which can be allocated to a virtual CPU.
3422
 
 *
3423
 
 * Returns 0 in case of success, -1 in case of failure.
3424
 
 */
3425
 
 
3426
 
int
3427
 
xenHypervisorPinVcpu(virDomainPtr domain, unsigned int vcpu,
3428
 
                     unsigned char *cpumap, int maplen)
3429
 
{
3430
 
    int ret;
3431
 
    xenUnifiedPrivatePtr priv;
3432
 
 
3433
 
    if (domain->conn == NULL)
3434
 
        return -1;
3435
 
 
3436
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3437
 
    if (priv->handle < 0 || (domain->id < 0) ||
3438
 
        (cpumap == NULL) || (maplen < 1))
3439
 
        return (-1);
3440
 
 
3441
 
    ret = virXen_setvcpumap(priv->handle, domain->id, vcpu,
3442
 
                            cpumap, maplen);
3443
 
    if (ret < 0)
3444
 
        return (-1);
3445
 
    return (0);
3446
 
}
3447
 
#endif
3448
 
 
3449
 
/**
3450
 
 * virDomainGetVcpus:
3451
 
 * @domain: pointer to domain object, or NULL for Domain0
3452
 
 * @info: pointer to an array of virVcpuInfo structures (OUT)
3453
 
 * @maxinfo: number of structures in info array
3454
 
 * @cpumaps: pointer to an bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
3455
 
 *      If cpumaps is NULL, then no cpumap information is returned by the API.
3456
 
 *      It's assumed there is <maxinfo> cpumap in cpumaps array.
3457
 
 *      The memory allocated to cpumaps must be (maxinfo * maplen) bytes
3458
 
 *      (ie: calloc(maxinfo, maplen)).
3459
 
 *      One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
3460
 
 * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
3461
 
 *      underlying virtualization system (Xen...).
3462
 
 *
3463
 
 * Extract information about virtual CPUs of domain, store it in info array
3464
 
 * and also in cpumaps if this pointer isn't NULL.
3465
 
 *
3466
 
 * Returns the number of info filled in case of success, -1 in case of failure.
3467
 
 */
3468
 
#ifndef PROXY
3469
 
int
3470
 
xenHypervisorGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
3471
 
                      unsigned char *cpumaps, int maplen)
3472
 
{
3473
 
    xen_getdomaininfo dominfo;
3474
 
    int ret;
3475
 
    xenUnifiedPrivatePtr priv;
3476
 
    virVcpuInfoPtr ipt;
3477
 
    int nbinfo, i;
3478
 
 
3479
 
    if (domain->conn == NULL)
3480
 
        return -1;
3481
 
 
3482
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3483
 
    if (priv->handle < 0 || (domain->id < 0) ||
3484
 
        (info == NULL) || (maxinfo < 1) ||
3485
 
        (sizeof(cpumap_t) & 7)) {
3486
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
3487
 
                        _("domain shut off or invalid"), 0);
3488
 
        return (-1);
3489
 
    }
3490
 
    if ((cpumaps != NULL) && (maplen < 1)) {
3491
 
        virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__,
3492
 
                        "invalid argument", 0);
3493
 
        return -1;
3494
 
    }
3495
 
    /* first get the number of virtual CPUs in this domain */
3496
 
    XEN_GETDOMAININFO_CLEAR(dominfo);
3497
 
    ret = virXen_getdomaininfo(priv->handle, domain->id,
3498
 
                               &dominfo);
3499
 
 
3500
 
    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != domain->id)) {
3501
 
        virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
3502
 
                        _("cannot get domain details"), 0);
3503
 
        return (-1);
3504
 
    }
3505
 
    nbinfo = XEN_GETDOMAININFO_CPUCOUNT(dominfo) + 1;
3506
 
    if (nbinfo > maxinfo) nbinfo = maxinfo;
3507
 
 
3508
 
    if (cpumaps != NULL)
3509
 
        memset(cpumaps, 0, maxinfo * maplen);
3510
 
 
3511
 
    for (i = 0, ipt = info; i < nbinfo; i++, ipt++) {
3512
 
        if ((cpumaps != NULL) && (i < maxinfo)) {
3513
 
            ret = virXen_getvcpusinfo(priv->handle, domain->id, i,
3514
 
                                      ipt,
3515
 
                                      (unsigned char *)VIR_GET_CPUMAP(cpumaps, maplen, i),
3516
 
                                      maplen);
3517
 
            if (ret < 0) {
3518
 
                virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
3519
 
                                _("cannot get VCPUs info"), 0);
3520
 
                return(-1);
3521
 
            }
3522
 
        } else {
3523
 
            ret = virXen_getvcpusinfo(priv->handle, domain->id, i,
3524
 
                                      ipt, NULL, 0);
3525
 
            if (ret < 0) {
3526
 
                virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
3527
 
                                _("cannot get VCPUs info"), 0);
3528
 
                return(-1);
3529
 
            }
3530
 
        }
3531
 
    }
3532
 
    return nbinfo;
3533
 
}
3534
 
#endif /* PROXY */
3535
 
 
3536
 
/**
3537
 
 * xenHypervisorGetVcpuMax:
3538
 
 *
3539
 
 *  Returns the maximum number of virtual CPUs supported for
3540
 
 *  the guest VM. If the guest is inactive, this is the maximum
3541
 
 *  of CPU defined by Xen. If the guest is running this reflect
3542
 
 *  the maximum number of virtual CPUs the guest was booted with.
3543
 
 */
3544
 
int
3545
 
xenHypervisorGetVcpuMax(virDomainPtr domain)
3546
 
{
3547
 
    xen_getdomaininfo dominfo;
3548
 
    int ret;
3549
 
    int maxcpu;
3550
 
    xenUnifiedPrivatePtr priv;
3551
 
 
3552
 
    if (domain->conn == NULL)
3553
 
        return -1;
3554
 
 
3555
 
    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
3556
 
    if (priv->handle < 0)
3557
 
        return (-1);
3558
 
 
3559
 
    /* inactive domain */
3560
 
    if (domain->id < 0) {
3561
 
        maxcpu = MAX_VIRT_CPUS;
3562
 
    } else {
3563
 
        XEN_GETDOMAININFO_CLEAR(dominfo);
3564
 
        ret = virXen_getdomaininfo(priv->handle, domain->id,
3565
 
                                   &dominfo);
3566
 
 
3567
 
        if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != domain->id))
3568
 
            return (-1);
3569
 
        maxcpu = XEN_GETDOMAININFO_MAXCPUID(dominfo) + 1;
3570
 
    }
3571
 
 
3572
 
    return maxcpu;
3573
 
}
3574
 
 
3575
 
/**
3576
 
 * xenHavePrivilege()
3577
 
 *
3578
 
 * Return true if the current process should be able to connect to Xen.
3579
 
 */
3580
 
int
3581
 
xenHavePrivilege()
3582
 
{
3583
 
#ifdef __sun
3584
 
    return priv_ineffect (PRIV_XVM_CONTROL);
3585
 
#else
3586
 
    return access(XEN_HYPERVISOR_SOCKET, R_OK) == 0;
3587
 
#endif
3588
 
}