hypercall.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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_fpu_taskswitch(int set)
  151. {
  152. return _hypercall1(int, fpu_taskswitch, set);
  153. }
  154. static inline int
  155. HYPERVISOR_sched_op(int cmd, unsigned long arg)
  156. {
  157. return _hypercall2(int, sched_op, cmd, arg);
  158. }
  159. static inline long
  160. HYPERVISOR_set_timer_op(u64 timeout)
  161. {
  162. unsigned long timeout_hi = (unsigned long)(timeout>>32);
  163. unsigned long timeout_lo = (unsigned long)timeout;
  164. return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
  165. }
  166. static inline int
  167. HYPERVISOR_set_debugreg(int reg, unsigned long value)
  168. {
  169. return _hypercall2(int, set_debugreg, reg, value);
  170. }
  171. static inline unsigned long
  172. HYPERVISOR_get_debugreg(int reg)
  173. {
  174. return _hypercall1(unsigned long, get_debugreg, reg);
  175. }
  176. static inline int
  177. HYPERVISOR_update_descriptor(u64 ma, u64 desc)
  178. {
  179. return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
  180. }
  181. static inline int
  182. HYPERVISOR_memory_op(unsigned int cmd, void *arg)
  183. {
  184. return _hypercall2(int, memory_op, cmd, arg);
  185. }
  186. static inline int
  187. HYPERVISOR_multicall(void *call_list, int nr_calls)
  188. {
  189. return _hypercall2(int, multicall, call_list, nr_calls);
  190. }
  191. static inline int
  192. HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
  193. unsigned long flags)
  194. {
  195. unsigned long pte_hi = 0;
  196. #ifdef CONFIG_X86_PAE
  197. pte_hi = new_val.pte_high;
  198. #endif
  199. return _hypercall4(int, update_va_mapping, va,
  200. new_val.pte_low, pte_hi, flags);
  201. }
  202. static inline int
  203. HYPERVISOR_event_channel_op(int cmd, void *arg)
  204. {
  205. int rc = _hypercall2(int, event_channel_op, cmd, arg);
  206. if (unlikely(rc == -ENOSYS)) {
  207. struct evtchn_op op;
  208. op.cmd = cmd;
  209. memcpy(&op.u, arg, sizeof(op.u));
  210. rc = _hypercall1(int, event_channel_op_compat, &op);
  211. memcpy(arg, &op.u, sizeof(op.u));
  212. }
  213. return rc;
  214. }
  215. static inline int
  216. HYPERVISOR_xen_version(int cmd, void *arg)
  217. {
  218. return _hypercall2(int, xen_version, cmd, arg);
  219. }
  220. static inline int
  221. HYPERVISOR_console_io(int cmd, int count, char *str)
  222. {
  223. return _hypercall3(int, console_io, cmd, count, str);
  224. }
  225. static inline int
  226. HYPERVISOR_physdev_op(int cmd, void *arg)
  227. {
  228. int rc = _hypercall2(int, physdev_op, cmd, arg);
  229. if (unlikely(rc == -ENOSYS)) {
  230. struct physdev_op op;
  231. op.cmd = cmd;
  232. memcpy(&op.u, arg, sizeof(op.u));
  233. rc = _hypercall1(int, physdev_op_compat, &op);
  234. memcpy(arg, &op.u, sizeof(op.u));
  235. }
  236. return rc;
  237. }
  238. static inline int
  239. HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
  240. {
  241. return _hypercall3(int, grant_table_op, cmd, uop, count);
  242. }
  243. static inline int
  244. HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
  245. unsigned long flags, domid_t domid)
  246. {
  247. unsigned long pte_hi = 0;
  248. #ifdef CONFIG_X86_PAE
  249. pte_hi = new_val.pte_high;
  250. #endif
  251. return _hypercall5(int, update_va_mapping_otherdomain, va,
  252. new_val.pte_low, pte_hi, flags, domid);
  253. }
  254. static inline int
  255. HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
  256. {
  257. return _hypercall2(int, vm_assist, cmd, type);
  258. }
  259. static inline int
  260. HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
  261. {
  262. return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
  263. }
  264. static inline int
  265. HYPERVISOR_suspend(unsigned long srec)
  266. {
  267. return _hypercall3(int, sched_op, SCHEDOP_shutdown,
  268. SHUTDOWN_suspend, srec);
  269. }
  270. static inline int
  271. HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
  272. {
  273. return _hypercall2(int, nmi_op, op, arg);
  274. }
  275. static inline void
  276. MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
  277. pte_t new_val, unsigned long flags)
  278. {
  279. mcl->op = __HYPERVISOR_update_va_mapping;
  280. mcl->args[0] = va;
  281. #ifdef CONFIG_X86_PAE
  282. mcl->args[1] = new_val.pte_low;
  283. mcl->args[2] = new_val.pte_high;
  284. #else
  285. mcl->args[1] = new_val.pte_low;
  286. mcl->args[2] = 0;
  287. #endif
  288. mcl->args[3] = flags;
  289. }
  290. static inline void
  291. MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
  292. void *uop, unsigned int count)
  293. {
  294. mcl->op = __HYPERVISOR_grant_table_op;
  295. mcl->args[0] = cmd;
  296. mcl->args[1] = (unsigned long)uop;
  297. mcl->args[2] = count;
  298. }
  299. static inline void
  300. MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
  301. pte_t new_val, unsigned long flags,
  302. domid_t domid)
  303. {
  304. mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
  305. mcl->args[0] = va;
  306. #ifdef CONFIG_X86_PAE
  307. mcl->args[1] = new_val.pte_low;
  308. mcl->args[2] = new_val.pte_high;
  309. #else
  310. mcl->args[1] = new_val.pte_low;
  311. mcl->args[2] = 0;
  312. #endif
  313. mcl->args[3] = flags;
  314. mcl->args[4] = domid;
  315. }
  316. static inline void
  317. MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
  318. struct desc_struct desc)
  319. {
  320. mcl->op = __HYPERVISOR_update_descriptor;
  321. mcl->args[0] = maddr;
  322. mcl->args[1] = maddr >> 32;
  323. mcl->args[2] = desc.a;
  324. mcl->args[3] = desc.b;
  325. }
  326. static inline void
  327. MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
  328. {
  329. mcl->op = __HYPERVISOR_memory_op;
  330. mcl->args[0] = cmd;
  331. mcl->args[1] = (unsigned long)arg;
  332. }
  333. static inline void
  334. MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
  335. int count, int *success_count, domid_t domid)
  336. {
  337. mcl->op = __HYPERVISOR_mmu_update;
  338. mcl->args[0] = (unsigned long)req;
  339. mcl->args[1] = count;
  340. mcl->args[2] = (unsigned long)success_count;
  341. mcl->args[3] = domid;
  342. }
  343. static inline void
  344. MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
  345. int *success_count, domid_t domid)
  346. {
  347. mcl->op = __HYPERVISOR_mmuext_op;
  348. mcl->args[0] = (unsigned long)op;
  349. mcl->args[1] = count;
  350. mcl->args[2] = (unsigned long)success_count;
  351. mcl->args[3] = domid;
  352. }
  353. static inline void
  354. MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
  355. {
  356. mcl->op = __HYPERVISOR_set_gdt;
  357. mcl->args[0] = (unsigned long)frames;
  358. mcl->args[1] = entries;
  359. }
  360. static inline void
  361. MULTI_stack_switch(struct multicall_entry *mcl,
  362. unsigned long ss, unsigned long esp)
  363. {
  364. mcl->op = __HYPERVISOR_stack_switch;
  365. mcl->args[0] = ss;
  366. mcl->args[1] = esp;
  367. }
  368. #endif /* __HYPERCALL_H__ */