hypercall.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /******************************************************************************
  2. * hypercall.h
  3. *
  4. * Linux-specific hypervisor handling.
  5. *
  6. * Copyright (c) 2002-2004, K A Fraser
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License version 2
  10. * as published by the Free Software Foundation; or, when distributed
  11. * separately from the Linux kernel or incorporated into other
  12. * software packages, subject to the following license:
  13. *
  14. * Permission is hereby granted, free of charge, to any person obtaining a copy
  15. * of this source file (the "Software"), to deal in the Software without
  16. * restriction, including without limitation the rights to use, copy, modify,
  17. * merge, publish, distribute, sublicense, and/or sell copies of the Software,
  18. * and to permit persons to whom the Software is furnished to do so, subject to
  19. * the following conditions:
  20. *
  21. * The above copyright notice and this permission notice shall be included in
  22. * all copies or substantial portions of the Software.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  27. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  28. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  29. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  30. * IN THE SOFTWARE.
  31. */
  32. #ifndef __HYPERCALL_H__
  33. #define __HYPERCALL_H__
  34. #include <linux/errno.h>
  35. #include <linux/string.h>
  36. #include <xen/interface/xen.h>
  37. #include <xen/interface/sched.h>
  38. #include <xen/interface/physdev.h>
  39. extern struct { char _entry[32]; } hypercall_page[];
  40. #define _hypercall0(type, name) \
  41. ({ \
  42. long __res; \
  43. asm volatile ( \
  44. "call %[call]" \
  45. : "=a" (__res) \
  46. : [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
  47. : "memory" ); \
  48. (type)__res; \
  49. })
  50. #define _hypercall1(type, name, a1) \
  51. ({ \
  52. long __res, __ign1; \
  53. asm volatile ( \
  54. "call %[call]" \
  55. : "=a" (__res), "=b" (__ign1) \
  56. : "1" ((long)(a1)), \
  57. [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
  58. : "memory" ); \
  59. (type)__res; \
  60. })
  61. #define _hypercall2(type, name, a1, a2) \
  62. ({ \
  63. long __res, __ign1, __ign2; \
  64. asm volatile ( \
  65. "call %[call]" \
  66. : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
  67. : "1" ((long)(a1)), "2" ((long)(a2)), \
  68. [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
  69. : "memory" ); \
  70. (type)__res; \
  71. })
  72. #define _hypercall3(type, name, a1, a2, a3) \
  73. ({ \
  74. long __res, __ign1, __ign2, __ign3; \
  75. asm volatile ( \
  76. "call %[call]" \
  77. : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
  78. "=d" (__ign3) \
  79. : "1" ((long)(a1)), "2" ((long)(a2)), \
  80. "3" ((long)(a3)), \
  81. [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
  82. : "memory" ); \
  83. (type)__res; \
  84. })
  85. #define _hypercall4(type, name, a1, a2, a3, a4) \
  86. ({ \
  87. long __res, __ign1, __ign2, __ign3, __ign4; \
  88. asm volatile ( \
  89. "call %[call]" \
  90. : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
  91. "=d" (__ign3), "=S" (__ign4) \
  92. : "1" ((long)(a1)), "2" ((long)(a2)), \
  93. "3" ((long)(a3)), "4" ((long)(a4)), \
  94. [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
  95. : "memory" ); \
  96. (type)__res; \
  97. })
  98. #define _hypercall5(type, name, a1, a2, a3, a4, a5) \
  99. ({ \
  100. long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
  101. asm volatile ( \
  102. "call %[call]" \
  103. : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
  104. "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
  105. : "1" ((long)(a1)), "2" ((long)(a2)), \
  106. "3" ((long)(a3)), "4" ((long)(a4)), \
  107. "5" ((long)(a5)), \
  108. [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
  109. : "memory" ); \
  110. (type)__res; \
  111. })
  112. static inline int
  113. HYPERVISOR_set_trap_table(struct trap_info *table)
  114. {
  115. return _hypercall1(int, set_trap_table, table);
  116. }
  117. static inline int
  118. HYPERVISOR_mmu_update(struct mmu_update *req, int count,
  119. int *success_count, domid_t domid)
  120. {
  121. return _hypercall4(int, mmu_update, req, count, success_count, domid);
  122. }
  123. static inline int
  124. HYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
  125. int *success_count, domid_t domid)
  126. {
  127. return _hypercall4(int, mmuext_op, op, count, success_count, domid);
  128. }
  129. static inline int
  130. HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
  131. {
  132. return _hypercall2(int, set_gdt, frame_list, entries);
  133. }
  134. static inline int
  135. HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
  136. {
  137. return _hypercall2(int, stack_switch, ss, esp);
  138. }
  139. static inline int
  140. HYPERVISOR_set_callbacks(unsigned long event_selector,
  141. unsigned long event_address,
  142. unsigned long failsafe_selector,
  143. unsigned long failsafe_address)
  144. {
  145. return _hypercall4(int, set_callbacks,
  146. event_selector, event_address,
  147. failsafe_selector, failsafe_address);
  148. }
  149. static inline int
  150. HYPERVISOR_callback_op(int cmd, void *arg)
  151. {
  152. return _hypercall2(int, callback_op, cmd, arg);
  153. }
  154. static inline int
  155. HYPERVISOR_fpu_taskswitch(int set)
  156. {
  157. return _hypercall1(int, fpu_taskswitch, set);
  158. }
  159. static inline int
  160. HYPERVISOR_sched_op(int cmd, unsigned long arg)
  161. {
  162. return _hypercall2(int, sched_op, cmd, arg);
  163. }
  164. static inline long
  165. HYPERVISOR_set_timer_op(u64 timeout)
  166. {
  167. unsigned long timeout_hi = (unsigned long)(timeout>>32);
  168. unsigned long timeout_lo = (unsigned long)timeout;
  169. return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
  170. }
  171. static inline int
  172. HYPERVISOR_set_debugreg(int reg, unsigned long value)
  173. {
  174. return _hypercall2(int, set_debugreg, reg, value);
  175. }
  176. static inline unsigned long
  177. HYPERVISOR_get_debugreg(int reg)
  178. {
  179. return _hypercall1(unsigned long, get_debugreg, reg);
  180. }
  181. static inline int
  182. HYPERVISOR_update_descriptor(u64 ma, u64 desc)
  183. {
  184. return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
  185. }
  186. static inline int
  187. HYPERVISOR_memory_op(unsigned int cmd, void *arg)
  188. {
  189. return _hypercall2(int, memory_op, cmd, arg);
  190. }
  191. static inline int
  192. HYPERVISOR_multicall(void *call_list, int nr_calls)
  193. {
  194. return _hypercall2(int, multicall, call_list, nr_calls);
  195. }
  196. static inline int
  197. HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
  198. unsigned long flags)
  199. {
  200. unsigned long pte_hi = 0;
  201. #ifdef CONFIG_X86_PAE
  202. pte_hi = new_val.pte_high;
  203. #endif
  204. return _hypercall4(int, update_va_mapping, va,
  205. new_val.pte_low, pte_hi, flags);
  206. }
  207. static inline int
  208. HYPERVISOR_event_channel_op(int cmd, void *arg)
  209. {
  210. int rc = _hypercall2(int, event_channel_op, cmd, arg);
  211. if (unlikely(rc == -ENOSYS)) {
  212. struct evtchn_op op;
  213. op.cmd = cmd;
  214. memcpy(&op.u, arg, sizeof(op.u));
  215. rc = _hypercall1(int, event_channel_op_compat, &op);
  216. memcpy(arg, &op.u, sizeof(op.u));
  217. }
  218. return rc;
  219. }
  220. static inline int
  221. HYPERVISOR_xen_version(int cmd, void *arg)
  222. {
  223. return _hypercall2(int, xen_version, cmd, arg);
  224. }
  225. static inline int
  226. HYPERVISOR_console_io(int cmd, int count, char *str)
  227. {
  228. return _hypercall3(int, console_io, cmd, count, str);
  229. }
  230. static inline int
  231. HYPERVISOR_physdev_op(int cmd, void *arg)
  232. {
  233. int rc = _hypercall2(int, physdev_op, cmd, arg);
  234. if (unlikely(rc == -ENOSYS)) {
  235. struct physdev_op op;
  236. op.cmd = cmd;
  237. memcpy(&op.u, arg, sizeof(op.u));
  238. rc = _hypercall1(int, physdev_op_compat, &op);
  239. memcpy(arg, &op.u, sizeof(op.u));
  240. }
  241. return rc;
  242. }
  243. static inline int
  244. HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
  245. {
  246. return _hypercall3(int, grant_table_op, cmd, uop, count);
  247. }
  248. static inline int
  249. HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
  250. unsigned long flags, domid_t domid)
  251. {
  252. unsigned long pte_hi = 0;
  253. #ifdef CONFIG_X86_PAE
  254. pte_hi = new_val.pte_high;
  255. #endif
  256. return _hypercall5(int, update_va_mapping_otherdomain, va,
  257. new_val.pte_low, pte_hi, flags, domid);
  258. }
  259. static inline int
  260. HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
  261. {
  262. return _hypercall2(int, vm_assist, cmd, type);
  263. }
  264. static inline int
  265. HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
  266. {
  267. return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
  268. }
  269. static inline int
  270. HYPERVISOR_suspend(unsigned long srec)
  271. {
  272. return _hypercall3(int, sched_op, SCHEDOP_shutdown,
  273. SHUTDOWN_suspend, srec);
  274. }
  275. static inline int
  276. HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
  277. {
  278. return _hypercall2(int, nmi_op, op, arg);
  279. }
  280. static inline void
  281. MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
  282. pte_t new_val, unsigned long flags)
  283. {
  284. mcl->op = __HYPERVISOR_update_va_mapping;
  285. mcl->args[0] = va;
  286. #ifdef CONFIG_X86_PAE
  287. mcl->args[1] = new_val.pte_low;
  288. mcl->args[2] = new_val.pte_high;
  289. #else
  290. mcl->args[1] = new_val.pte_low;
  291. mcl->args[2] = 0;
  292. #endif
  293. mcl->args[3] = flags;
  294. }
  295. static inline void
  296. MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
  297. void *uop, unsigned int count)
  298. {
  299. mcl->op = __HYPERVISOR_grant_table_op;
  300. mcl->args[0] = cmd;
  301. mcl->args[1] = (unsigned long)uop;
  302. mcl->args[2] = count;
  303. }
  304. static inline void
  305. MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
  306. pte_t new_val, unsigned long flags,
  307. domid_t domid)
  308. {
  309. mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
  310. mcl->args[0] = va;
  311. #ifdef CONFIG_X86_PAE
  312. mcl->args[1] = new_val.pte_low;
  313. mcl->args[2] = new_val.pte_high;
  314. #else
  315. mcl->args[1] = new_val.pte_low;
  316. mcl->args[2] = 0;
  317. #endif
  318. mcl->args[3] = flags;
  319. mcl->args[4] = domid;
  320. }
  321. static inline void
  322. MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
  323. struct desc_struct desc)
  324. {
  325. mcl->op = __HYPERVISOR_update_descriptor;
  326. mcl->args[0] = maddr;
  327. mcl->args[1] = maddr >> 32;
  328. mcl->args[2] = desc.a;
  329. mcl->args[3] = desc.b;
  330. }
  331. static inline void
  332. MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
  333. {
  334. mcl->op = __HYPERVISOR_memory_op;
  335. mcl->args[0] = cmd;
  336. mcl->args[1] = (unsigned long)arg;
  337. }
  338. static inline void
  339. MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
  340. int count, int *success_count, domid_t domid)
  341. {
  342. mcl->op = __HYPERVISOR_mmu_update;
  343. mcl->args[0] = (unsigned long)req;
  344. mcl->args[1] = count;
  345. mcl->args[2] = (unsigned long)success_count;
  346. mcl->args[3] = domid;
  347. }
  348. static inline void
  349. MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
  350. int *success_count, domid_t domid)
  351. {
  352. mcl->op = __HYPERVISOR_mmuext_op;
  353. mcl->args[0] = (unsigned long)op;
  354. mcl->args[1] = count;
  355. mcl->args[2] = (unsigned long)success_count;
  356. mcl->args[3] = domid;
  357. }
  358. static inline void
  359. MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
  360. {
  361. mcl->op = __HYPERVISOR_set_gdt;
  362. mcl->args[0] = (unsigned long)frames;
  363. mcl->args[1] = entries;
  364. }
  365. static inline void
  366. MULTI_stack_switch(struct multicall_entry *mcl,
  367. unsigned long ss, unsigned long esp)
  368. {
  369. mcl->op = __HYPERVISOR_stack_switch;
  370. mcl->args[0] = ss;
  371. mcl->args[1] = esp;
  372. }
  373. #endif /* __HYPERCALL_H__ */