PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/libvirt-0.9.11/src/xen/xen_hypervisor.c

#
C | 3720 lines | 2636 code | 476 blank | 608 comment | 591 complexity | f2299dc4a0741d9f9279da5608c34bc1 MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * xen_internal.c: direct access to Xen hypervisor level
  3. *
  4. * Copyright (C) 2005-2012 Red Hat, Inc.
  5. *
  6. * See COPYING.LIB for the License of this software
  7. *
  8. * Daniel Veillard <veillard@redhat.com>
  9. */
  10. #include <config.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. /* required for uint8_t, uint32_t, etc ... */
  14. #include <stdint.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <unistd.h>
  18. #include <fcntl.h>
  19. #include <sys/mman.h>
  20. #include <sys/ioctl.h>
  21. #include <limits.h>
  22. #include <stdint.h>
  23. #include <regex.h>
  24. #include <errno.h>
  25. #include <sys/utsname.h>
  26. #ifdef __sun
  27. # include <sys/systeminfo.h>
  28. # include <priv.h>
  29. # ifndef PRIV_XVM_CONTROL
  30. # define PRIV_XVM_CONTROL ((const char *)"xvm_control")
  31. # endif
  32. #endif /* __sun */
  33. /* required for dom0_getdomaininfo_t */
  34. #include <xen/dom0_ops.h>
  35. #include <xen/version.h>
  36. #ifdef HAVE_XEN_LINUX_PRIVCMD_H
  37. # include <xen/linux/privcmd.h>
  38. #else
  39. # ifdef HAVE_XEN_SYS_PRIVCMD_H
  40. # include <xen/sys/privcmd.h>
  41. # endif
  42. #endif
  43. /* required for shutdown flags */
  44. #include <xen/sched.h>
  45. #include "virterror_internal.h"
  46. #include "logging.h"
  47. #include "datatypes.h"
  48. #include "driver.h"
  49. #include "util.h"
  50. #include "xen_driver.h"
  51. #include "xen_hypervisor.h"
  52. #include "xs_internal.h"
  53. #include "stats_linux.h"
  54. #include "block_stats.h"
  55. #include "xend_internal.h"
  56. #include "buf.h"
  57. #include "capabilities.h"
  58. #include "memory.h"
  59. #include "virfile.h"
  60. #include "virnodesuspend.h"
  61. #include "virtypedparam.h"
  62. #define VIR_FROM_THIS VIR_FROM_XEN
  63. /*
  64. * so far there is 2 versions of the structures usable for doing
  65. * hypervisor calls.
  66. */
  67. /* the old one */
  68. typedef struct v0_hypercall_struct {
  69. unsigned long op;
  70. unsigned long arg[5];
  71. } v0_hypercall_t;
  72. #ifdef __linux__
  73. # define XEN_V0_IOCTL_HYPERCALL_CMD \
  74. _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t))
  75. /* the new one */
  76. typedef struct v1_hypercall_struct
  77. {
  78. uint64_t op;
  79. uint64_t arg[5];
  80. } v1_hypercall_t;
  81. # define XEN_V1_IOCTL_HYPERCALL_CMD \
  82. _IOC(_IOC_NONE, 'P', 0, sizeof(v1_hypercall_t))
  83. typedef v1_hypercall_t hypercall_t;
  84. #elif defined(__sun)
  85. typedef privcmd_hypercall_t hypercall_t;
  86. #else
  87. # error "unsupported platform"
  88. #endif
  89. #ifndef __HYPERVISOR_sysctl
  90. # define __HYPERVISOR_sysctl 35
  91. #endif
  92. #ifndef __HYPERVISOR_domctl
  93. # define __HYPERVISOR_domctl 36
  94. #endif
  95. #ifdef WITH_RHEL5_API
  96. # define SYS_IFACE_MIN_VERS_NUMA 3
  97. #else
  98. # define SYS_IFACE_MIN_VERS_NUMA 4
  99. #endif
  100. static int xen_ioctl_hypercall_cmd = 0;
  101. static int initialized = 0;
  102. static int in_init = 0;
  103. static struct xenHypervisorVersions hv_versions = {
  104. .hv = 0,
  105. .hypervisor = 2,
  106. .sys_interface = -1,
  107. .dom_interface = -1,
  108. };
  109. static int kb_per_pages = 0;
  110. /* Regular expressions used by xenHypervisorGetCapabilities, and
  111. * compiled once by xenHypervisorInit. Note that these are POSIX.2
  112. * extended regular expressions (regex(7)).
  113. */
  114. static const char *flags_hvm_re = "^flags[[:blank:]]+:.* (vmx|svm)[[:space:]]";
  115. static regex_t flags_hvm_rec;
  116. static const char *flags_pae_re = "^flags[[:blank:]]+:.* pae[[:space:]]";
  117. static regex_t flags_pae_rec;
  118. static const char *xen_cap_re = "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x86_64|ia64|powerpc64)(p|be)?";
  119. static regex_t xen_cap_rec;
  120. /*
  121. * The content of the structures for a getdomaininfolist system hypercall
  122. */
  123. #ifndef DOMFLAGS_DYING
  124. # define DOMFLAGS_DYING (1<<0) /* Domain is scheduled to die. */
  125. # define DOMFLAGS_HVM (1<<1) /* Domain is HVM */
  126. # define DOMFLAGS_SHUTDOWN (1<<2) /* The guest OS has shut down. */
  127. # define DOMFLAGS_PAUSED (1<<3) /* Currently paused by control software. */
  128. # define DOMFLAGS_BLOCKED (1<<4) /* Currently blocked pending an event. */
  129. # define DOMFLAGS_RUNNING (1<<5) /* Domain is currently running. */
  130. # define DOMFLAGS_CPUMASK 255 /* CPU to which this domain is bound. */
  131. # define DOMFLAGS_CPUSHIFT 8
  132. # define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code. */
  133. # define DOMFLAGS_SHUTDOWNSHIFT 16
  134. #endif
  135. /*
  136. * These flags explain why a system is in the state of "shutdown". Normally,
  137. * They are defined in xen/sched.h
  138. */
  139. #ifndef SHUTDOWN_poweroff
  140. # define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
  141. # define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
  142. # define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
  143. # define SHUTDOWN_crash 3 /* Tell controller we've crashed. */
  144. #endif
  145. #define XEN_V0_OP_GETDOMAININFOLIST 38
  146. #define XEN_V1_OP_GETDOMAININFOLIST 38
  147. #define XEN_V2_OP_GETDOMAININFOLIST 6
  148. struct xen_v0_getdomaininfo {
  149. domid_t domain; /* the domain number */
  150. uint32_t flags; /* flags, see before */
  151. uint64_t tot_pages; /* total number of pages used */
  152. uint64_t max_pages; /* maximum number of pages allowed */
  153. unsigned long shared_info_frame; /* MFN of shared_info struct */
  154. uint64_t cpu_time; /* CPU time used */
  155. uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
  156. uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
  157. uint32_t ssidref;
  158. xen_domain_handle_t handle;
  159. };
  160. typedef struct xen_v0_getdomaininfo xen_v0_getdomaininfo;
  161. struct xen_v2_getdomaininfo {
  162. domid_t domain; /* the domain number */
  163. uint32_t flags; /* flags, see before */
  164. uint64_t tot_pages; /* total number of pages used */
  165. uint64_t max_pages; /* maximum number of pages allowed */
  166. uint64_t shared_info_frame; /* MFN of shared_info struct */
  167. uint64_t cpu_time; /* CPU time used */
  168. uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
  169. uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
  170. uint32_t ssidref;
  171. xen_domain_handle_t handle;
  172. };
  173. typedef struct xen_v2_getdomaininfo xen_v2_getdomaininfo;
  174. /* As of Hypervisor Call v2, DomCtl v5 we are now 8-byte aligned
  175. even on 32-bit archs when dealing with uint64_t */
  176. #define ALIGN_64 __attribute__((aligned(8)))
  177. struct xen_v2d5_getdomaininfo {
  178. domid_t domain; /* the domain number */
  179. uint32_t flags; /* flags, see before */
  180. uint64_t tot_pages ALIGN_64; /* total number of pages used */
  181. uint64_t max_pages ALIGN_64; /* maximum number of pages allowed */
  182. uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
  183. uint64_t cpu_time ALIGN_64; /* CPU time used */
  184. uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
  185. uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
  186. uint32_t ssidref;
  187. xen_domain_handle_t handle;
  188. };
  189. typedef struct xen_v2d5_getdomaininfo xen_v2d5_getdomaininfo;
  190. struct xen_v2d6_getdomaininfo {
  191. domid_t domain; /* the domain number */
  192. uint32_t flags; /* flags, see before */
  193. uint64_t tot_pages ALIGN_64; /* total number of pages used */
  194. uint64_t max_pages ALIGN_64; /* maximum number of pages allowed */
  195. uint64_t shr_pages ALIGN_64; /* number of shared pages */
  196. uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
  197. uint64_t cpu_time ALIGN_64; /* CPU time used */
  198. uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
  199. uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
  200. uint32_t ssidref;
  201. xen_domain_handle_t handle;
  202. };
  203. typedef struct xen_v2d6_getdomaininfo xen_v2d6_getdomaininfo;
  204. struct xen_v2d7_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 shr_pages ALIGN_64; /* number of shared pages */
  210. uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
  211. uint64_t cpu_time ALIGN_64; /* CPU time used */
  212. uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
  213. uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
  214. uint32_t ssidref;
  215. xen_domain_handle_t handle;
  216. uint32_t cpupool;
  217. };
  218. typedef struct xen_v2d7_getdomaininfo xen_v2d7_getdomaininfo;
  219. struct xen_v2d8_getdomaininfo {
  220. domid_t domain; /* the domain number */
  221. uint32_t flags; /* flags, see before */
  222. uint64_t tot_pages ALIGN_64; /* total number of pages used */
  223. uint64_t max_pages ALIGN_64; /* maximum number of pages allowed */
  224. uint64_t shr_pages ALIGN_64; /* number of shared pages */
  225. uint64_t paged_pages ALIGN_64; /* number of paged pages */
  226. uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
  227. uint64_t cpu_time ALIGN_64; /* CPU time used */
  228. uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
  229. uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
  230. uint32_t ssidref;
  231. xen_domain_handle_t handle;
  232. uint32_t cpupool;
  233. };
  234. typedef struct xen_v2d8_getdomaininfo xen_v2d8_getdomaininfo;
  235. union xen_getdomaininfo {
  236. struct xen_v0_getdomaininfo v0;
  237. struct xen_v2_getdomaininfo v2;
  238. struct xen_v2d5_getdomaininfo v2d5;
  239. struct xen_v2d6_getdomaininfo v2d6;
  240. struct xen_v2d7_getdomaininfo v2d7;
  241. struct xen_v2d8_getdomaininfo v2d8;
  242. };
  243. typedef union xen_getdomaininfo xen_getdomaininfo;
  244. union xen_getdomaininfolist {
  245. struct xen_v0_getdomaininfo *v0;
  246. struct xen_v2_getdomaininfo *v2;
  247. struct xen_v2d5_getdomaininfo *v2d5;
  248. struct xen_v2d6_getdomaininfo *v2d6;
  249. struct xen_v2d7_getdomaininfo *v2d7;
  250. struct xen_v2d8_getdomaininfo *v2d8;
  251. };
  252. typedef union xen_getdomaininfolist xen_getdomaininfolist;
  253. struct xen_v2_getschedulerid {
  254. uint32_t sched_id; /* Get Scheduler ID from Xen */
  255. };
  256. typedef struct xen_v2_getschedulerid xen_v2_getschedulerid;
  257. union xen_getschedulerid {
  258. struct xen_v2_getschedulerid *v2;
  259. };
  260. typedef union xen_getschedulerid xen_getschedulerid;
  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. typedef struct xen_v2s4_availheap xen_v2s4_availheap;
  268. struct xen_v2s5_availheap {
  269. uint32_t min_bitwidth; /* Smallest address width (zero if don't care). */
  270. uint32_t max_bitwidth; /* Largest address width (zero if don't care). */
  271. int32_t node; /* NUMA node (-1 for sum across all nodes). */
  272. uint64_t avail_bytes ALIGN_64; /* Bytes available in the specified region. */
  273. };
  274. typedef struct xen_v2s5_availheap xen_v2s5_availheap;
  275. #define XEN_GETDOMAININFOLIST_ALLOC(domlist, size) \
  276. (hv_versions.hypervisor < 2 ? \
  277. (VIR_ALLOC_N(domlist.v0, (size)) == 0) : \
  278. (hv_versions.dom_interface >= 8 ? \
  279. (VIR_ALLOC_N(domlist.v2d8, (size)) == 0) : \
  280. (hv_versions.dom_interface == 7 ? \
  281. (VIR_ALLOC_N(domlist.v2d7, (size)) == 0) : \
  282. (hv_versions.dom_interface == 6 ? \
  283. (VIR_ALLOC_N(domlist.v2d6, (size)) == 0) : \
  284. (hv_versions.dom_interface == 5 ? \
  285. (VIR_ALLOC_N(domlist.v2d5, (size)) == 0) : \
  286. (VIR_ALLOC_N(domlist.v2, (size)) == 0))))))
  287. #define XEN_GETDOMAININFOLIST_FREE(domlist) \
  288. (hv_versions.hypervisor < 2 ? \
  289. VIR_FREE(domlist.v0) : \
  290. (hv_versions.dom_interface >= 8 ? \
  291. VIR_FREE(domlist.v2d8) : \
  292. (hv_versions.dom_interface == 7 ? \
  293. VIR_FREE(domlist.v2d7) : \
  294. (hv_versions.dom_interface == 6 ? \
  295. VIR_FREE(domlist.v2d6) : \
  296. (hv_versions.dom_interface == 5 ? \
  297. VIR_FREE(domlist.v2d5) : \
  298. VIR_FREE(domlist.v2))))))
  299. #define XEN_GETDOMAININFOLIST_CLEAR(domlist, size) \
  300. (hv_versions.hypervisor < 2 ? \
  301. memset(domlist.v0, 0, sizeof(*domlist.v0) * size) : \
  302. (hv_versions.dom_interface >= 8 ? \
  303. memset(domlist.v2d8, 0, sizeof(*domlist.v2d8) * size) : \
  304. (hv_versions.dom_interface == 7 ? \
  305. memset(domlist.v2d7, 0, sizeof(*domlist.v2d7) * size) : \
  306. (hv_versions.dom_interface == 6 ? \
  307. memset(domlist.v2d6, 0, sizeof(*domlist.v2d6) * size) : \
  308. (hv_versions.dom_interface == 5 ? \
  309. memset(domlist.v2d5, 0, sizeof(*domlist.v2d5) * size) : \
  310. memset(domlist.v2, 0, sizeof(*domlist.v2) * size))))))
  311. #define XEN_GETDOMAININFOLIST_DOMAIN(domlist, n) \
  312. (hv_versions.hypervisor < 2 ? \
  313. domlist.v0[n].domain : \
  314. (hv_versions.dom_interface >= 8 ? \
  315. domlist.v2d8[n].domain : \
  316. (hv_versions.dom_interface == 7 ? \
  317. domlist.v2d7[n].domain : \
  318. (hv_versions.dom_interface == 6 ? \
  319. domlist.v2d6[n].domain : \
  320. (hv_versions.dom_interface == 5 ? \
  321. domlist.v2d5[n].domain : \
  322. domlist.v2[n].domain)))))
  323. #define XEN_GETDOMAININFOLIST_UUID(domlist, n) \
  324. (hv_versions.hypervisor < 2 ? \
  325. domlist.v0[n].handle : \
  326. (hv_versions.dom_interface >= 8 ? \
  327. domlist.v2d8[n].handle : \
  328. (hv_versions.dom_interface == 7 ? \
  329. domlist.v2d7[n].handle : \
  330. (hv_versions.dom_interface == 6 ? \
  331. domlist.v2d6[n].handle : \
  332. (hv_versions.dom_interface == 5 ? \
  333. domlist.v2d5[n].handle : \
  334. domlist.v2[n].handle)))))
  335. #define XEN_GETDOMAININFOLIST_DATA(domlist) \
  336. (hv_versions.hypervisor < 2 ? \
  337. (void*)(domlist->v0) : \
  338. (hv_versions.dom_interface >= 8 ? \
  339. (void*)(domlist->v2d8) : \
  340. (hv_versions.dom_interface == 7 ? \
  341. (void*)(domlist->v2d7) : \
  342. (hv_versions.dom_interface == 6 ? \
  343. (void*)(domlist->v2d6) : \
  344. (hv_versions.dom_interface == 5 ? \
  345. (void*)(domlist->v2d5) : \
  346. (void*)(domlist->v2))))))
  347. #define XEN_GETDOMAININFO_SIZE \
  348. (hv_versions.hypervisor < 2 ? \
  349. sizeof(xen_v0_getdomaininfo) : \
  350. (hv_versions.dom_interface >= 8 ? \
  351. sizeof(xen_v2d8_getdomaininfo) : \
  352. (hv_versions.dom_interface == 7 ? \
  353. sizeof(xen_v2d7_getdomaininfo) : \
  354. (hv_versions.dom_interface == 6 ? \
  355. sizeof(xen_v2d6_getdomaininfo) : \
  356. (hv_versions.dom_interface == 5 ? \
  357. sizeof(xen_v2d5_getdomaininfo) : \
  358. sizeof(xen_v2_getdomaininfo))))))
  359. #define XEN_GETDOMAININFO_CLEAR(dominfo) \
  360. (hv_versions.hypervisor < 2 ? \
  361. memset(&(dominfo.v0), 0, sizeof(xen_v0_getdomaininfo)) : \
  362. (hv_versions.dom_interface >= 8 ? \
  363. memset(&(dominfo.v2d8), 0, sizeof(xen_v2d8_getdomaininfo)) : \
  364. (hv_versions.dom_interface == 7 ? \
  365. memset(&(dominfo.v2d7), 0, sizeof(xen_v2d7_getdomaininfo)) : \
  366. (hv_versions.dom_interface == 6 ? \
  367. memset(&(dominfo.v2d6), 0, sizeof(xen_v2d6_getdomaininfo)) : \
  368. (hv_versions.dom_interface == 5 ? \
  369. memset(&(dominfo.v2d5), 0, sizeof(xen_v2d5_getdomaininfo)) : \
  370. memset(&(dominfo.v2), 0, sizeof(xen_v2_getdomaininfo)))))))
  371. #define XEN_GETDOMAININFO_DOMAIN(dominfo) \
  372. (hv_versions.hypervisor < 2 ? \
  373. dominfo.v0.domain : \
  374. (hv_versions.dom_interface >= 8 ? \
  375. dominfo.v2d8.domain : \
  376. (hv_versions.dom_interface == 7 ? \
  377. dominfo.v2d7.domain : \
  378. (hv_versions.dom_interface == 6 ? \
  379. dominfo.v2d6.domain : \
  380. (hv_versions.dom_interface == 5 ? \
  381. dominfo.v2d5.domain : \
  382. dominfo.v2.domain)))))
  383. #define XEN_GETDOMAININFO_CPUTIME(dominfo) \
  384. (hv_versions.hypervisor < 2 ? \
  385. dominfo.v0.cpu_time : \
  386. (hv_versions.dom_interface >= 8 ? \
  387. dominfo.v2d8.cpu_time : \
  388. (hv_versions.dom_interface == 7 ? \
  389. dominfo.v2d7.cpu_time : \
  390. (hv_versions.dom_interface == 6 ? \
  391. dominfo.v2d6.cpu_time : \
  392. (hv_versions.dom_interface == 5 ? \
  393. dominfo.v2d5.cpu_time : \
  394. dominfo.v2.cpu_time)))))
  395. #define XEN_GETDOMAININFO_CPUCOUNT(dominfo) \
  396. (hv_versions.hypervisor < 2 ? \
  397. dominfo.v0.nr_online_vcpus : \
  398. (hv_versions.dom_interface >= 8 ? \
  399. dominfo.v2d8.nr_online_vcpus : \
  400. (hv_versions.dom_interface == 7 ? \
  401. dominfo.v2d7.nr_online_vcpus : \
  402. (hv_versions.dom_interface == 6 ? \
  403. dominfo.v2d6.nr_online_vcpus : \
  404. (hv_versions.dom_interface == 5 ? \
  405. dominfo.v2d5.nr_online_vcpus : \
  406. dominfo.v2.nr_online_vcpus)))))
  407. #define XEN_GETDOMAININFO_MAXCPUID(dominfo) \
  408. (hv_versions.hypervisor < 2 ? \
  409. dominfo.v0.max_vcpu_id : \
  410. (hv_versions.dom_interface >= 8 ? \
  411. dominfo.v2d8.max_vcpu_id : \
  412. (hv_versions.dom_interface == 7 ? \
  413. dominfo.v2d7.max_vcpu_id : \
  414. (hv_versions.dom_interface == 6 ? \
  415. dominfo.v2d6.max_vcpu_id : \
  416. (hv_versions.dom_interface == 5 ? \
  417. dominfo.v2d5.max_vcpu_id : \
  418. dominfo.v2.max_vcpu_id)))))
  419. #define XEN_GETDOMAININFO_FLAGS(dominfo) \
  420. (hv_versions.hypervisor < 2 ? \
  421. dominfo.v0.flags : \
  422. (hv_versions.dom_interface >= 8 ? \
  423. dominfo.v2d8.flags : \
  424. (hv_versions.dom_interface == 7 ? \
  425. dominfo.v2d7.flags : \
  426. (hv_versions.dom_interface == 6 ? \
  427. dominfo.v2d6.flags : \
  428. (hv_versions.dom_interface == 5 ? \
  429. dominfo.v2d5.flags : \
  430. dominfo.v2.flags)))))
  431. #define XEN_GETDOMAININFO_TOT_PAGES(dominfo) \
  432. (hv_versions.hypervisor < 2 ? \
  433. dominfo.v0.tot_pages : \
  434. (hv_versions.dom_interface >= 8 ? \
  435. dominfo.v2d8.tot_pages : \
  436. (hv_versions.dom_interface == 7 ? \
  437. dominfo.v2d7.tot_pages : \
  438. (hv_versions.dom_interface == 6 ? \
  439. dominfo.v2d6.tot_pages : \
  440. (hv_versions.dom_interface == 5 ? \
  441. dominfo.v2d5.tot_pages : \
  442. dominfo.v2.tot_pages)))))
  443. #define XEN_GETDOMAININFO_MAX_PAGES(dominfo) \
  444. (hv_versions.hypervisor < 2 ? \
  445. dominfo.v0.max_pages : \
  446. (hv_versions.dom_interface >= 8 ? \
  447. dominfo.v2d8.max_pages : \
  448. (hv_versions.dom_interface == 7 ? \
  449. dominfo.v2d7.max_pages : \
  450. (hv_versions.dom_interface == 6 ? \
  451. dominfo.v2d6.max_pages : \
  452. (hv_versions.dom_interface == 5 ? \
  453. dominfo.v2d5.max_pages : \
  454. dominfo.v2.max_pages)))))
  455. #define XEN_GETDOMAININFO_UUID(dominfo) \
  456. (hv_versions.hypervisor < 2 ? \
  457. dominfo.v0.handle : \
  458. (hv_versions.dom_interface >= 8 ? \
  459. dominfo.v2d8.handle : \
  460. (hv_versions.dom_interface == 7 ? \
  461. dominfo.v2d7.handle : \
  462. (hv_versions.dom_interface == 6 ? \
  463. dominfo.v2d6.handle : \
  464. (hv_versions.dom_interface == 5 ? \
  465. dominfo.v2d5.handle : \
  466. dominfo.v2.handle)))))
  467. static int
  468. lock_pages(void *addr, size_t len)
  469. {
  470. #ifdef __linux__
  471. return mlock(addr, len);
  472. #elif defined(__sun)
  473. return 0;
  474. #endif
  475. }
  476. static int
  477. unlock_pages(void *addr, size_t len)
  478. {
  479. #ifdef __linux__
  480. return munlock(addr, len);
  481. #elif defined(__sun)
  482. return 0;
  483. #endif
  484. }
  485. struct xen_v0_getdomaininfolistop {
  486. domid_t first_domain;
  487. uint32_t max_domains;
  488. struct xen_v0_getdomaininfo *buffer;
  489. uint32_t num_domains;
  490. };
  491. typedef struct xen_v0_getdomaininfolistop xen_v0_getdomaininfolistop;
  492. struct xen_v2_getdomaininfolistop {
  493. domid_t first_domain;
  494. uint32_t max_domains;
  495. struct xen_v2_getdomaininfo *buffer;
  496. uint32_t num_domains;
  497. };
  498. typedef struct xen_v2_getdomaininfolistop xen_v2_getdomaininfolistop;
  499. /* As of HV version 2, sysctl version 3 the *buffer pointer is 64-bit aligned */
  500. struct xen_v2s3_getdomaininfolistop {
  501. domid_t first_domain;
  502. uint32_t max_domains;
  503. #ifdef __BIG_ENDIAN__
  504. struct {
  505. int __pad[(sizeof(long long) - sizeof(struct xen_v2d5_getdomaininfo *)) / sizeof(int)];
  506. struct xen_v2d5_getdomaininfo *v;
  507. } buffer;
  508. #else
  509. union {
  510. struct xen_v2d5_getdomaininfo *v;
  511. uint64_t pad ALIGN_64;
  512. } buffer;
  513. #endif
  514. uint32_t num_domains;
  515. };
  516. typedef struct xen_v2s3_getdomaininfolistop xen_v2s3_getdomaininfolistop;
  517. struct xen_v0_domainop {
  518. domid_t domain;
  519. };
  520. typedef struct xen_v0_domainop xen_v0_domainop;
  521. /*
  522. * The information for a destroydomain system hypercall
  523. */
  524. #define XEN_V0_OP_DESTROYDOMAIN 9
  525. #define XEN_V1_OP_DESTROYDOMAIN 9
  526. #define XEN_V2_OP_DESTROYDOMAIN 2
  527. /*
  528. * The information for a pausedomain system hypercall
  529. */
  530. #define XEN_V0_OP_PAUSEDOMAIN 10
  531. #define XEN_V1_OP_PAUSEDOMAIN 10
  532. #define XEN_V2_OP_PAUSEDOMAIN 3
  533. /*
  534. * The information for an unpausedomain system hypercall
  535. */
  536. #define XEN_V0_OP_UNPAUSEDOMAIN 11
  537. #define XEN_V1_OP_UNPAUSEDOMAIN 11
  538. #define XEN_V2_OP_UNPAUSEDOMAIN 4
  539. /*
  540. * The information for a setmaxmem system hypercall
  541. */
  542. #define XEN_V0_OP_SETMAXMEM 28
  543. #define XEN_V1_OP_SETMAXMEM 28
  544. #define XEN_V2_OP_SETMAXMEM 11
  545. struct xen_v0_setmaxmem {
  546. domid_t domain;
  547. uint64_t maxmem;
  548. };
  549. typedef struct xen_v0_setmaxmem xen_v0_setmaxmem;
  550. typedef struct xen_v0_setmaxmem xen_v1_setmaxmem;
  551. struct xen_v2_setmaxmem {
  552. uint64_t maxmem;
  553. };
  554. typedef struct xen_v2_setmaxmem xen_v2_setmaxmem;
  555. struct xen_v2d5_setmaxmem {
  556. uint64_t maxmem ALIGN_64;
  557. };
  558. typedef struct xen_v2d5_setmaxmem xen_v2d5_setmaxmem;
  559. /*
  560. * The information for a setmaxvcpu system hypercall
  561. */
  562. #define XEN_V0_OP_SETMAXVCPU 41
  563. #define XEN_V1_OP_SETMAXVCPU 41
  564. #define XEN_V2_OP_SETMAXVCPU 15
  565. struct xen_v0_setmaxvcpu {
  566. domid_t domain;
  567. uint32_t maxvcpu;
  568. };
  569. typedef struct xen_v0_setmaxvcpu xen_v0_setmaxvcpu;
  570. typedef struct xen_v0_setmaxvcpu xen_v1_setmaxvcpu;
  571. struct xen_v2_setmaxvcpu {
  572. uint32_t maxvcpu;
  573. };
  574. typedef struct xen_v2_setmaxvcpu xen_v2_setmaxvcpu;
  575. /*
  576. * The information for a setvcpumap system hypercall
  577. * Note that between 1 and 2 the limitation to 64 physical CPU was lifted
  578. * hence the difference in structures
  579. */
  580. #define XEN_V0_OP_SETVCPUMAP 20
  581. #define XEN_V1_OP_SETVCPUMAP 20
  582. #define XEN_V2_OP_SETVCPUMAP 9
  583. struct xen_v0_setvcpumap {
  584. domid_t domain;
  585. uint32_t vcpu;
  586. cpumap_t cpumap;
  587. };
  588. typedef struct xen_v0_setvcpumap xen_v0_setvcpumap;
  589. typedef struct xen_v0_setvcpumap xen_v1_setvcpumap;
  590. struct xen_v2_cpumap {
  591. uint8_t *bitmap;
  592. uint32_t nr_cpus;
  593. };
  594. struct xen_v2_setvcpumap {
  595. uint32_t vcpu;
  596. struct xen_v2_cpumap cpumap;
  597. };
  598. typedef struct xen_v2_setvcpumap xen_v2_setvcpumap;
  599. /* HV version 2, Dom version 5 requires 64-bit alignment */
  600. struct xen_v2d5_cpumap {
  601. #ifdef __BIG_ENDIAN__
  602. struct {
  603. int __pad[(sizeof(long long) - sizeof(uint8_t *)) / sizeof(int)];
  604. uint8_t *v;
  605. } bitmap;
  606. #else
  607. union {
  608. uint8_t *v;
  609. uint64_t pad ALIGN_64;
  610. } bitmap;
  611. #endif
  612. uint32_t nr_cpus;
  613. };
  614. struct xen_v2d5_setvcpumap {
  615. uint32_t vcpu;
  616. struct xen_v2d5_cpumap cpumap;
  617. };
  618. typedef struct xen_v2d5_setvcpumap xen_v2d5_setvcpumap;
  619. /*
  620. * The information for a vcpuinfo system hypercall
  621. */
  622. #define XEN_V0_OP_GETVCPUINFO 43
  623. #define XEN_V1_OP_GETVCPUINFO 43
  624. #define XEN_V2_OP_GETVCPUINFO 14
  625. struct xen_v0_vcpuinfo {
  626. domid_t domain; /* owner's domain */
  627. uint32_t vcpu; /* the vcpu number */
  628. uint8_t online; /* seen as on line */
  629. uint8_t blocked; /* blocked on event */
  630. uint8_t running; /* scheduled on CPU */
  631. uint64_t cpu_time; /* nanosecond of CPU used */
  632. uint32_t cpu; /* current mapping */
  633. cpumap_t cpumap; /* deprecated in V2 */
  634. };
  635. typedef struct xen_v0_vcpuinfo xen_v0_vcpuinfo;
  636. typedef struct xen_v0_vcpuinfo xen_v1_vcpuinfo;
  637. struct xen_v2_vcpuinfo {
  638. uint32_t vcpu; /* the vcpu number */
  639. uint8_t online; /* seen as on line */
  640. uint8_t blocked; /* blocked on event */
  641. uint8_t running; /* scheduled on CPU */
  642. uint64_t cpu_time; /* nanosecond of CPU used */
  643. uint32_t cpu; /* current mapping */
  644. };
  645. typedef struct xen_v2_vcpuinfo xen_v2_vcpuinfo;
  646. struct xen_v2d5_vcpuinfo {
  647. uint32_t vcpu; /* the vcpu number */
  648. uint8_t online; /* seen as on line */
  649. uint8_t blocked; /* blocked on event */
  650. uint8_t running; /* scheduled on CPU */
  651. uint64_t cpu_time ALIGN_64; /* nanosecond of CPU used */
  652. uint32_t cpu; /* current mapping */
  653. };
  654. typedef struct xen_v2d5_vcpuinfo xen_v2d5_vcpuinfo;
  655. /*
  656. * from V2 the pinning of a vcpu is read with a separate call
  657. */
  658. #define XEN_V2_OP_GETVCPUMAP 25
  659. typedef struct xen_v2_setvcpumap xen_v2_getvcpumap;
  660. typedef struct xen_v2d5_setvcpumap xen_v2d5_getvcpumap;
  661. /*
  662. * from V2 we get the scheduler information
  663. */
  664. #define XEN_V2_OP_GETSCHEDULERID 4
  665. /*
  666. * from V2 we get the available heap information
  667. */
  668. #define XEN_V2_OP_GETAVAILHEAP 9
  669. /*
  670. * from V2 we get the scheduler parameter
  671. */
  672. #define XEN_V2_OP_SCHEDULER 16
  673. /* Scheduler types. */
  674. #define XEN_SCHEDULER_SEDF 4
  675. #define XEN_SCHEDULER_CREDIT 5
  676. /* get/set scheduler parameters */
  677. #define XEN_DOMCTL_SCHEDOP_putinfo 0
  678. #define XEN_DOMCTL_SCHEDOP_getinfo 1
  679. struct xen_v2_setschedinfo {
  680. uint32_t sched_id;
  681. uint32_t cmd;
  682. union {
  683. struct xen_domctl_sched_sedf {
  684. uint64_t period ALIGN_64;
  685. uint64_t slice ALIGN_64;
  686. uint64_t latency ALIGN_64;
  687. uint32_t extratime;
  688. uint32_t weight;
  689. } sedf;
  690. struct xen_domctl_sched_credit {
  691. uint16_t weight;
  692. uint16_t cap;
  693. } credit;
  694. } u;
  695. };
  696. typedef struct xen_v2_setschedinfo xen_v2_setschedinfo;
  697. typedef struct xen_v2_setschedinfo xen_v2_getschedinfo;
  698. /*
  699. * The hypercall operation structures also have changed on
  700. * changeset 86d26e6ec89b
  701. */
  702. /* the old structure */
  703. struct xen_op_v0 {
  704. uint32_t cmd;
  705. uint32_t interface_version;
  706. union {
  707. xen_v0_getdomaininfolistop getdomaininfolist;
  708. xen_v0_domainop domain;
  709. xen_v0_setmaxmem setmaxmem;
  710. xen_v0_setmaxvcpu setmaxvcpu;
  711. xen_v0_setvcpumap setvcpumap;
  712. xen_v0_vcpuinfo getvcpuinfo;
  713. uint8_t padding[128];
  714. } u;
  715. };
  716. typedef struct xen_op_v0 xen_op_v0;
  717. typedef struct xen_op_v0 xen_op_v1;
  718. /* the new structure for systems operations */
  719. struct xen_op_v2_sys {
  720. uint32_t cmd;
  721. uint32_t interface_version;
  722. union {
  723. xen_v2_getdomaininfolistop getdomaininfolist;
  724. xen_v2s3_getdomaininfolistop getdomaininfolists3;
  725. xen_v2_getschedulerid getschedulerid;
  726. xen_v2s4_availheap availheap;
  727. xen_v2s5_availheap availheap5;
  728. uint8_t padding[128];
  729. } u;
  730. };
  731. typedef struct xen_op_v2_sys xen_op_v2_sys;
  732. /* the new structure for domains operation */
  733. struct xen_op_v2_dom {
  734. uint32_t cmd;
  735. uint32_t interface_version;
  736. domid_t domain;
  737. union {
  738. xen_v2_setmaxmem setmaxmem;
  739. xen_v2d5_setmaxmem setmaxmemd5;
  740. xen_v2_setmaxvcpu setmaxvcpu;
  741. xen_v2_setvcpumap setvcpumap;
  742. xen_v2d5_setvcpumap setvcpumapd5;
  743. xen_v2_vcpuinfo getvcpuinfo;
  744. xen_v2d5_vcpuinfo getvcpuinfod5;
  745. xen_v2_getvcpumap getvcpumap;
  746. xen_v2d5_getvcpumap getvcpumapd5;
  747. xen_v2_setschedinfo setschedinfo;
  748. xen_v2_getschedinfo getschedinfo;
  749. uint8_t padding[128];
  750. } u;
  751. };
  752. typedef struct xen_op_v2_dom xen_op_v2_dom;
  753. #ifdef __linux__
  754. # define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
  755. # define HYPERVISOR_CAPABILITIES "/sys/hypervisor/properties/capabilities"
  756. #elif defined(__sun)
  757. # define XEN_HYPERVISOR_SOCKET "/dev/xen/privcmd"
  758. #else
  759. # error "unsupported platform"
  760. #endif
  761. static unsigned long long xenHypervisorGetMaxMemory(virDomainPtr domain);
  762. struct xenUnifiedDriver xenHypervisorDriver = {
  763. .xenClose = xenHypervisorClose,
  764. .xenVersion = xenHypervisorGetVersion,
  765. .xenDomainSuspend = xenHypervisorPauseDomain,
  766. .xenDomainResume = xenHypervisorResumeDomain,
  767. .xenDomainDestroyFlags = xenHypervisorDestroyDomainFlags,
  768. .xenDomainGetOSType = xenHypervisorDomainGetOSType,
  769. .xenDomainGetMaxMemory = xenHypervisorGetMaxMemory,
  770. .xenDomainSetMaxMemory = xenHypervisorSetMaxMemory,
  771. .xenDomainGetInfo = xenHypervisorGetDomainInfo,
  772. .xenDomainPinVcpu = xenHypervisorPinVcpu,
  773. .xenDomainGetVcpus = xenHypervisorGetVcpus,
  774. .xenDomainGetSchedulerType = xenHypervisorGetSchedulerType,
  775. .xenDomainGetSchedulerParameters = xenHypervisorGetSchedulerParameters,
  776. .xenDomainSetSchedulerParameters = xenHypervisorSetSchedulerParameters,
  777. };
  778. #define virXenError(code, ...) \
  779. if (in_init == 0) \
  780. virReportErrorHelper(VIR_FROM_XEN, code, __FILE__, \
  781. __FUNCTION__, __LINE__, __VA_ARGS__)
  782. /**
  783. * xenHypervisorDoV0Op:
  784. * @handle: the handle to the Xen hypervisor
  785. * @op: pointer to the hypervisor operation structure
  786. *
  787. * Do a hypervisor operation though the old interface,
  788. * this leads to a hypervisor call through ioctl.
  789. *
  790. * Returns 0 in case of success and -1 in case of error.
  791. */
  792. static int
  793. xenHypervisorDoV0Op(int handle, xen_op_v0 * op)
  794. {
  795. int ret;
  796. v0_hypercall_t hc;
  797. memset(&hc, 0, sizeof(hc));
  798. op->interface_version = hv_versions.hv << 8;
  799. hc.op = __HYPERVISOR_dom0_op;
  800. hc.arg[0] = (unsigned long) op;
  801. if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
  802. virXenError(VIR_ERR_XEN_CALL, " locking");
  803. return -1;
  804. }
  805. ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
  806. if (ret < 0) {
  807. virXenError(VIR_ERR_XEN_CALL, " ioctl %d",
  808. xen_ioctl_hypercall_cmd);
  809. }
  810. if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
  811. virXenError(VIR_ERR_XEN_CALL, " releasing");
  812. ret = -1;
  813. }
  814. if (ret < 0)
  815. return -1;
  816. return 0;
  817. }
  818. /**
  819. * xenHypervisorDoV1Op:
  820. * @handle: the handle to the Xen hypervisor
  821. * @op: pointer to the hypervisor operation structure
  822. *
  823. * Do a hypervisor v1 operation, this leads to a hypervisor call through
  824. * ioctl.
  825. *
  826. * Returns 0 in case of success and -1 in case of error.
  827. */
  828. static int
  829. xenHypervisorDoV1Op(int handle, xen_op_v1* op)
  830. {
  831. int ret;
  832. hypercall_t hc;
  833. memset(&hc, 0, sizeof(hc));
  834. op->interface_version = DOM0_INTERFACE_VERSION;
  835. hc.op = __HYPERVISOR_dom0_op;
  836. hc.arg[0] = (unsigned long) op;
  837. if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
  838. virXenError(VIR_ERR_XEN_CALL, " locking");
  839. return -1;
  840. }
  841. ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
  842. if (ret < 0) {
  843. virXenError(VIR_ERR_XEN_CALL, " ioctl %d",
  844. xen_ioctl_hypercall_cmd);
  845. }
  846. if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
  847. virXenError(VIR_ERR_XEN_CALL, " releasing");
  848. ret = -1;
  849. }
  850. if (ret < 0)
  851. return -1;
  852. return 0;
  853. }
  854. /**
  855. * xenHypervisorDoV2Sys:
  856. * @handle: the handle to the Xen hypervisor
  857. * @op: pointer to the hypervisor operation structure
  858. *
  859. * Do a hypervisor v2 system operation, this leads to a hypervisor
  860. * call through ioctl.
  861. *
  862. * Returns 0 in case of success and -1 in case of error.
  863. */
  864. static int
  865. xenHypervisorDoV2Sys(int handle, xen_op_v2_sys* op)
  866. {
  867. int ret;
  868. hypercall_t hc;
  869. memset(&hc, 0, sizeof(hc));
  870. op->interface_version = hv_versions.sys_interface;
  871. hc.op = __HYPERVISOR_sysctl;
  872. hc.arg[0] = (unsigned long) op;
  873. if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
  874. virXenError(VIR_ERR_XEN_CALL, " locking");
  875. return -1;
  876. }
  877. ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
  878. if (ret < 0) {
  879. virXenError(VIR_ERR_XEN_CALL, " sys ioctl %d",
  880. xen_ioctl_hypercall_cmd);
  881. }
  882. if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
  883. virXenError(VIR_ERR_XEN_CALL, " releasing");
  884. ret = -1;
  885. }
  886. if (ret < 0)
  887. return -1;
  888. return 0;
  889. }
  890. /**
  891. * xenHypervisorDoV2Dom:
  892. * @handle: the handle to the Xen hypervisor
  893. * @op: pointer to the hypervisor domain operation structure
  894. *
  895. * Do a hypervisor v2 domain operation, this leads to a hypervisor
  896. * call through ioctl.
  897. *
  898. * Returns 0 in case of success and -1 in case of error.
  899. */
  900. static int
  901. xenHypervisorDoV2Dom(int handle, xen_op_v2_dom* op)
  902. {
  903. int ret;
  904. hypercall_t hc;
  905. memset(&hc, 0, sizeof(hc));
  906. op->interface_version = hv_versions.dom_interface;
  907. hc.op = __HYPERVISOR_domctl;
  908. hc.arg[0] = (unsigned long) op;
  909. if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
  910. virXenError(VIR_ERR_XEN_CALL, " locking");
  911. return -1;
  912. }
  913. ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
  914. if (ret < 0) {
  915. virXenError(VIR_ERR_XEN_CALL, " ioctl %d",
  916. xen_ioctl_hypercall_cmd);
  917. }
  918. if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
  919. virXenError(VIR_ERR_XEN_CALL, " releasing");
  920. ret = -1;
  921. }
  922. if (ret < 0)
  923. return -1;
  924. return 0;
  925. }
  926. /**
  927. * virXen_getdomaininfolist:
  928. * @handle: the hypervisor handle
  929. * @first_domain: first domain in the range
  930. * @maxids: maximum number of domains to list
  931. * @dominfos: output structures
  932. *
  933. * Do a low level hypercall to list existing domains information
  934. *
  935. * Returns the number of domains or -1 in case of failure
  936. */
  937. static int
  938. virXen_getdomaininfolist(int handle, int first_domain, int maxids,
  939. xen_getdomaininfolist *dominfos)
  940. {
  941. int ret = -1;
  942. if (lock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
  943. XEN_GETDOMAININFO_SIZE * maxids) < 0) {
  944. virXenError(VIR_ERR_XEN_CALL, " locking");
  945. return -1;
  946. }
  947. if (hv_versions.hypervisor > 1) {
  948. xen_op_v2_sys op;
  949. memset(&op, 0, sizeof(op));
  950. op.cmd = XEN_V2_OP_GETDOMAININFOLIST;
  951. if (hv_versions.sys_interface < 3) {
  952. op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
  953. op.u.getdomaininfolist.max_domains = maxids;
  954. op.u.getdomaininfolist.buffer = dominfos->v2;
  955. op.u.getdomaininfolist.num_domains = maxids;
  956. } else {
  957. op.u.getdomaininfolists3.first_domain = (domid_t) first_domain;
  958. op.u.getdomaininfolists3.max_domains = maxids;
  959. op.u.getdomaininfolists3.buffer.v = dominfos->v2d5;
  960. op.u.getdomaininfolists3.num_domains = maxids;
  961. }
  962. ret = xenHypervisorDoV2Sys(handle, &op);
  963. if (ret == 0) {
  964. if (hv_versions.sys_interface < 3)
  965. ret = op.u.getdomaininfolist.num_domains;
  966. else
  967. ret = op.u.getdomaininfolists3.num_domains;
  968. }
  969. } else if (hv_versions.hypervisor == 1) {
  970. xen_op_v1 op;
  971. memset(&op, 0, sizeof(op));
  972. op.cmd = XEN_V1_OP_GETDOMAININFOLIST;
  973. op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
  974. op.u.getdomaininfolist.max_domains = maxids;
  975. op.u.getdomaininfolist.buffer = dominfos->v0;
  976. op.u.getdomaininfolist.num_domains = maxids;
  977. ret = xenHypervisorDoV1Op(handle, &op);
  978. if (ret == 0)
  979. ret = op.u.getdomaininfolist.num_domains;
  980. } else if (hv_versions.hypervisor == 0) {
  981. xen_op_v0 op;
  982. memset(&op, 0, sizeof(op));
  983. op.cmd = XEN_V0_OP_GETDOMAININFOLIST;
  984. op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
  985. op.u.getdomaininfolist.max_domains = maxids;
  986. op.u.getdomaininfolist.buffer = dominfos->v0;
  987. op.u.getdomaininfolist.num_domains = maxids;
  988. ret = xenHypervisorDoV0Op(handle, &op);
  989. if (ret == 0)
  990. ret = op.u.getdomaininfolist.num_domains;
  991. }
  992. if (unlock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
  993. XEN_GETDOMAININFO_SIZE * maxids) < 0) {
  994. virXenError(VIR_ERR_XEN_CALL, " release");
  995. ret = -1;
  996. }
  997. return ret;
  998. }
  999. static int
  1000. virXen_getdomaininfo(int handle, int first_domain,
  1001. xen_getdomaininfo *dominfo) {
  1002. xen_getdomaininfolist dominfos;
  1003. if (hv_versions.hypervisor < 2) {
  1004. dominfos.v0 = &(dominfo->v0);
  1005. } else {
  1006. dominfos.v2 = &(dominfo->v2);
  1007. }
  1008. return virXen_getdomaininfolist(handle, first_domain, 1, &dominfos);
  1009. }
  1010. /**
  1011. * xenHypervisorGetSchedulerType:
  1012. * @domain: pointer to the Xen Hypervisor block
  1013. * @nparams:give a number of scheduler parameters.
  1014. *
  1015. * Do a low level hypercall to get scheduler type
  1016. *
  1017. * Returns scheduler name or NULL in case of failure
  1018. */
  1019. char *
  1020. xenHypervisorGetSchedulerType(virDomainPtr domain, int *nparams)
  1021. {
  1022. char *schedulertype = NULL;
  1023. xenUnifiedPrivatePtr priv;
  1024. if (domain->conn == NULL) {
  1025. virXenError(VIR_ERR_INTERNAL_ERROR, "%s",
  1026. _("domain or conn is NULL"));
  1027. return NULL;
  1028. }
  1029. priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
  1030. if (priv->handle < 0) {
  1031. virXenError(VIR_ERR_INTERNAL_ERROR, "%s",
  1032. _("priv->handle invalid"));
  1033. return NULL;
  1034. }
  1035. if (domain->id < 0) {
  1036. virXenError(VIR_ERR_OPERATION_INVALID,
  1037. "%s", _("domain is not running"));
  1038. return NULL;
  1039. }
  1040. /*
  1041. * Support only hv_versions.dom_interface >=5
  1042. * (Xen3.1.0 or later)
  1043. * TODO: check on Xen 3.0.3
  1044. */
  1045. if (hv_versions.dom_interface < 5) {
  1046. virXenError(VIR_ERR_NO_XEN, "%s",
  1047. _("unsupported in dom interface < 5"));
  1048. return NULL;
  1049. }
  1050. if (hv_versions.hypervisor > 1) {
  1051. xen_op_v2_sys op;
  1052. int ret;
  1053. memset(&op, 0, sizeof(op));
  1054. op.cmd = XEN_V2_OP_GETSCHEDULERID;
  1055. ret = xenHypervisorDoV2Sys(priv->handle, &op);
  1056. if (ret < 0)
  1057. return NULL;
  1058. switch (op.u.getschedulerid.sched_id){
  1059. case XEN_SCHEDULER_SEDF:
  1060. schedulertype = strdup("sedf");
  1061. if (schedulertype == NULL)
  1062. virReportOOMError();
  1063. if (nparams)
  1064. *nparams = XEN_SCHED_SEDF_NPARAM;
  1065. break;
  1066. case XEN_SCHEDULER_CREDIT:
  1067. schedulertype = strdup("credit");
  1068. if (schedulertype == NULL)
  1069. virReportOOMError();
  1070. if (nparams)
  1071. *nparams = XEN_SCHED_CRED_NPARAM;
  1072. break;
  1073. default:
  1074. break;
  1075. }
  1076. }
  1077. return schedulertype;
  1078. }
  1079. /**
  1080. * xenHypervisorGetSchedulerParameters:
  1081. * @domain: pointer to the Xen Hypervisor block
  1082. * @params: pointer to scheduler parameters.
  1083. * This memory area should be allocated before calling.
  1084. * @nparams: this parameter must be at least as large as
  1085. * the given number of scheduler parameters.
  1086. * from xenHypervisorGetSchedulerType().
  1087. *
  1088. * Do a low level hypercall to get scheduler parameters
  1089. *
  1090. * Returns 0 or -1 in case of failure
  1091. */
  1092. int
  1093. xenHypervisorGetSchedulerParameters(virDomainPtr domain,
  1094. virTypedParameterPtr params, int *nparams)
  1095. {
  1096. xenUnifiedPrivatePtr priv;
  1097. if (domain->conn == NULL) {
  1098. virXenError(VIR_ERR_INTERNAL_ERROR, "%s",
  1099. _("domain or conn is NULL"));
  1100. return -1;
  1101. }
  1102. priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
  1103. if (priv->handle < 0) {
  1104. virXenError(VIR_ERR_INTERNAL_ERROR, "%s",
  1105. _("priv->handle invalid"));
  1106. return -1;
  1107. }
  1108. if (domain->id < 0) {
  1109. virXenError(VIR_ERR_OPERATION_INVALID,
  1110. "%s", _("domain is not running"));
  1111. return -1;
  1112. }
  1113. /*
  1114. * Support only hv_versions.dom_interface >=5
  1115. * (Xen3.1.0 or later)
  1116. * TODO: check on Xen 3.0.3
  1117. */
  1118. if (hv_versions.dom_interface < 5) {
  1119. virXenError(VIR_ERR_NO_XEN, "%s",
  1120. _("unsupported in dom interface < 5"));
  1121. return -1;
  1122. }
  1123. if (hv_versions.hypervisor > 1) {
  1124. xen_op_v2_sys op_sys;
  1125. xen_op_v2_dom op_dom;
  1126. int ret;
  1127. memset(&op_sys, 0, sizeof(op_sys));
  1128. op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
  1129. ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
  1130. if (ret < 0)
  1131. return -1;
  1132. switch (op_sys.u.getschedulerid.sched_id){
  1133. case XEN_SCHEDULER_SEDF:
  1134. if (*nparams < XEN_SCHED_SEDF_NPARAM) {
  1135. virXenError(VIR_ERR_INVALID_ARG,
  1136. "%s", _("Invalid parameter count"));
  1137. return -1;
  1138. }
  1139. /* TODO: Implement for Xen/SEDF */
  1140. TODO
  1141. return -1;
  1142. case XEN_SCHEDULER_CREDIT:
  1143. memset(&op_dom, 0, sizeof(op_dom));
  1144. op_dom.cmd = XEN_V2_OP_SCHEDULER;
  1145. op_dom.domain = (domid_t) domain->id;
  1146. op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
  1147. op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
  1148. ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
  1149. if (ret < 0)
  1150. return -1;
  1151. if (virTypedParameterAssign(&params[0],
  1152. VIR_DOMAIN_SCHEDULER_WEIGHT,
  1153. VIR_TYPED_PARAM_UINT,
  1154. op_dom.u.getschedinfo.u.credit.weight) < 0)
  1155. return -1;
  1156. if (*nparams > 1 &&
  1157. virTypedParameterAssign(&params[1],
  1158. VIR_DOMAIN_SCHEDULER_CAP,
  1159. VIR_TYPED_PARAM_UINT,
  1160. op_dom.u.getschedinfo.u.credit.cap) < 0)
  1161. return -1;
  1162. if (*nparams > XEN_SCHED_CRED_NPARAM)
  1163. *nparams = XEN_SCHED_CRED_NPARAM;
  1164. break;
  1165. default:
  1166. virXenError(VIR_ERR_INVALID_ARG,
  1167. _("Unknown scheduler %d"),
  1168. op_sys.u.getschedulerid.sched_id);
  1169. return -1;
  1170. }
  1171. }
  1172. return 0;
  1173. }
  1174. /**
  1175. * xenHypervisorSetSchedulerParameters:
  1176. * @domain: pointer to the Xen Hypervisor block
  1177. * @nparams:give a number of scheduler setting parameters .
  1178. *
  1179. * Do a low level hypercall to set scheduler parameters
  1180. *
  1181. * Returns 0 or -1 in case of failure
  1182. */
  1183. int
  1184. xenHypervisorSetSchedulerParameters(virDomainPtr domain,
  1185. virTypedParameterPtr params, int nparams)
  1186. {
  1187. int i;
  1188. unsigned int val;
  1189. xenUnifiedPrivatePtr priv;
  1190. char buf[256];
  1191. if (domain->conn == NULL) {
  1192. virXenError(VIR_ERR_INTERNAL_ERROR, "%s",
  1193. _("domain or conn is NULL"));
  1194. return -1;
  1195. }
  1196. if (nparams == 0) {
  1197. /* nothing to do, exit early */
  1198. return 0;
  1199. }
  1200. if (virTypedParameterArrayValidate(params, nparams,
  1201. VIR_DOMAIN_SCHEDULER_WEIGHT,
  1202. VIR_TYPED_PARAM_UINT,
  1203. VIR_DOMAIN_SCHEDULER_CAP,
  1204. VIR_TYPED_PARAM_UINT,
  1205. NULL) < 0)
  1206. return -1;
  1207. priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
  1208. if (priv->handle < 0) {
  1209. virXenError(VIR_ERR_INTERNAL_ERROR, "%s",
  1210. _("priv->handle invalid"));
  1211. return -1;
  1212. }
  1213. if (domain->id < 0) {
  1214. virXenError(VIR_ERR_OPERATION_INVALID,
  1215. "%s", _("domain is not running"));
  1216. return -1;
  1217. }
  1218. /*
  1219. * Support only hv_versions.dom_interface >=5
  1220. * (Xen3.1.0 or later)
  1221. * TODO: check on Xen 3.0.3
  1222. */
  1223. if (hv_versions.dom_interface < 5) {
  1224. virXenError(VIR_ERR_NO_XEN, "%s",
  1225. _("unsupported in dom interface < 5"));
  1226. return -1;
  1227. }
  1228. if (hv_versions.hypervisor > 1) {
  1229. xen_op_v2_sys op_sys;
  1230. xen_op_v2_dom op_dom;
  1231. int ret;
  1232. memset(&op_sys, 0, sizeof(op_sys));
  1233. op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
  1234. ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
  1235. if (ret == -1) return -1;
  1236. switch (op_sys.u.getschedulerid.sched_id){
  1237. case XEN_SCHEDULER_SEDF:
  1238. /* TODO: Implement for Xen/SEDF */
  1239. TODO
  1240. return -1;
  1241. case XEN_SCHEDULER_CREDIT: {
  1242. memset(&op_dom, 0, sizeof(op_dom));
  1243. op_dom.cmd = XEN_V2_OP_SCHEDULER;
  1244. op_dom.domain = (domid_t) domain->id;
  1245. op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
  1246. op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
  1247. /*
  1248. * credit scheduler parameters
  1249. * following values do not change the parameters
  1250. */
  1251. op_dom.u.getschedinfo.u.credit.weight = 0;
  1252. op_dom.u.getschedinfo.u.credit.cap = (uint16_t)~0U;
  1253. for (i = 0; i < nparams; i++) {
  1254. memset(&buf, 0, sizeof(buf));
  1255. if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
  1256. val = params[i].value.ui;
  1257. if ((val < 1) || (val > USHRT_MAX)) {
  1258. virXenError(VIR_ERR_INVALID_ARG,
  1259. _("Credit scheduler weight parameter (%d) "
  1260. "is out of range (1-65535)"), val);
  1261. return -1;
  1262. }
  1263. op_dom.u.getschedinfo.u.credit.weight = val;
  1264. } else if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_CAP)) {
  1265. val = params[i].value.ui;
  1266. if (val >= USHRT_MAX) {
  1267. virXenError(VIR_ERR_INVALID_ARG,
  1268. _("Credit scheduler cap parameter (%d) is "
  1269. "out of range (0-65534)"), val);
  1270. return -1;
  1271. }
  1272. op_dom.u.getschedinfo.u.credit.cap = val;
  1273. }
  1274. }
  1275. ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
  1276. if (ret < 0)
  1277. return -1;
  1278. break;
  1279. }
  1280. default:
  1281. virXenError(VIR_ERR_INVALID_ARG,
  1282. _("Unknown scheduler %d"),
  1283. op_sys.u.getschedulerid.sched_id);
  1284. return -1;
  1285. }
  1286. }
  1287. return 0;
  1288. }
  1289. int
  1290. xenHypervisorDomainBlockStats (virDomainPtr dom,
  1291. const char *path,
  1292. struct _virDomainBlockStats *stats)
  1293. {
  1294. #ifdef __linux__
  1295. xenUnifiedPrivatePtr priv;
  1296. int ret;
  1297. priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
  1298. xenUnifiedLock(priv);
  1299. /* Need to lock because it hits the xenstore handle :-( */
  1300. ret = xenLinuxDomainBlockStats (priv, dom, path, stats);
  1301. xenUnifiedUnlock(priv);
  1302. return ret;
  1303. #else
  1304. virXenError(VIR_ERR_OPERATION_INVALID, "%s",
  1305. _("block statistics not supported on this platform"));
  1306. return -1;
  1307. #endif
  1308. }
  1309. /* Paths have the form vif<domid>.<n> (this interface checks that
  1310. * <domid> is the real domain ID and returns an error if not).
  1311. *
  1312. * In future we may allow you to query bridge stats (virbrX or
  1313. * xenbrX), but that will probably be through a separate
  1314. * virNetwork interface, as yet not decided.
  1315. */
  1316. int
  1317. xenHypervisorDomainInterfaceStats (virDomainPtr dom,
  1318. const char *path,
  1319. struct _virDomainInterfaceStats *stats)
  1320. {
  1321. #ifdef __linux__
  1322. int rqdomid, device;
  1323. /* Verify that the vif requested is one belonging to the current
  1324. * domain.
  1325. */
  1326. if (sscanf(path, "vif%d.%d", &rqdomid, &device) != 2) {
  1327. virXenError(VIR_ERR_INVALID_ARG, "%s",
  1328. _("invalid path, should be vif<domid>.<n>."));
  1329. return -1;
  1330. }
  1331. if (rqdomid != dom->id) {
  1332. virXenError(VIR_ERR_INVALID_ARG, "%s",
  1333. _("in…

Large files files are truncated, but you can click here to view the full file