hypercalls.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* Actual hypercalls, which allow guests to actually do something.
  2. Copyright (C) 2006 Rusty Russell IBM Corporation
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  14. */
  15. #include <linux/uaccess.h>
  16. #include <linux/syscalls.h>
  17. #include <linux/mm.h>
  18. #include <asm/page.h>
  19. #include <asm/pgtable.h>
  20. #include <irq_vectors.h>
  21. #include "lg.h"
  22. static void do_hcall(struct lguest *lg, struct lguest_regs *regs)
  23. {
  24. switch (regs->eax) {
  25. case LHCALL_FLUSH_ASYNC:
  26. break;
  27. case LHCALL_LGUEST_INIT:
  28. kill_guest(lg, "already have lguest_data");
  29. break;
  30. case LHCALL_CRASH: {
  31. char msg[128];
  32. lgread(lg, msg, regs->edx, sizeof(msg));
  33. msg[sizeof(msg)-1] = '\0';
  34. kill_guest(lg, "CRASH: %s", msg);
  35. break;
  36. }
  37. case LHCALL_FLUSH_TLB:
  38. if (regs->edx)
  39. guest_pagetable_clear_all(lg);
  40. else
  41. guest_pagetable_flush_user(lg);
  42. break;
  43. case LHCALL_GET_WALLCLOCK: {
  44. struct timespec ts;
  45. ktime_get_real_ts(&ts);
  46. regs->eax = ts.tv_sec;
  47. break;
  48. }
  49. case LHCALL_BIND_DMA:
  50. regs->eax = bind_dma(lg, regs->edx, regs->ebx,
  51. regs->ecx >> 8, regs->ecx & 0xFF);
  52. break;
  53. case LHCALL_SEND_DMA:
  54. send_dma(lg, regs->edx, regs->ebx);
  55. break;
  56. case LHCALL_LOAD_GDT:
  57. load_guest_gdt(lg, regs->edx, regs->ebx);
  58. break;
  59. case LHCALL_LOAD_IDT_ENTRY:
  60. load_guest_idt_entry(lg, regs->edx, regs->ebx, regs->ecx);
  61. break;
  62. case LHCALL_NEW_PGTABLE:
  63. guest_new_pagetable(lg, regs->edx);
  64. break;
  65. case LHCALL_SET_STACK:
  66. guest_set_stack(lg, regs->edx, regs->ebx, regs->ecx);
  67. break;
  68. case LHCALL_SET_PTE:
  69. guest_set_pte(lg, regs->edx, regs->ebx, mkgpte(regs->ecx));
  70. break;
  71. case LHCALL_SET_PMD:
  72. guest_set_pmd(lg, regs->edx, regs->ebx);
  73. break;
  74. case LHCALL_LOAD_TLS:
  75. guest_load_tls(lg, regs->edx);
  76. break;
  77. case LHCALL_SET_CLOCKEVENT:
  78. guest_set_clockevent(lg, regs->edx);
  79. break;
  80. case LHCALL_TS:
  81. lg->ts = regs->edx;
  82. break;
  83. case LHCALL_HALT:
  84. lg->halted = 1;
  85. break;
  86. default:
  87. kill_guest(lg, "Bad hypercall %li\n", regs->eax);
  88. }
  89. }
  90. /* We always do queued calls before actual hypercall. */
  91. static void do_async_hcalls(struct lguest *lg)
  92. {
  93. unsigned int i;
  94. u8 st[LHCALL_RING_SIZE];
  95. if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st)))
  96. return;
  97. for (i = 0; i < ARRAY_SIZE(st); i++) {
  98. struct lguest_regs regs;
  99. unsigned int n = lg->next_hcall;
  100. if (st[n] == 0xFF)
  101. break;
  102. if (++lg->next_hcall == LHCALL_RING_SIZE)
  103. lg->next_hcall = 0;
  104. if (get_user(regs.eax, &lg->lguest_data->hcalls[n].eax)
  105. || get_user(regs.edx, &lg->lguest_data->hcalls[n].edx)
  106. || get_user(regs.ecx, &lg->lguest_data->hcalls[n].ecx)
  107. || get_user(regs.ebx, &lg->lguest_data->hcalls[n].ebx)) {
  108. kill_guest(lg, "Fetching async hypercalls");
  109. break;
  110. }
  111. do_hcall(lg, &regs);
  112. if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) {
  113. kill_guest(lg, "Writing result for async hypercall");
  114. break;
  115. }
  116. if (lg->dma_is_pending)
  117. break;
  118. }
  119. }
  120. static void initialize(struct lguest *lg)
  121. {
  122. u32 tsc_speed;
  123. if (lg->regs->eax != LHCALL_LGUEST_INIT) {
  124. kill_guest(lg, "hypercall %li before LGUEST_INIT",
  125. lg->regs->eax);
  126. return;
  127. }
  128. /* We only tell the guest to use the TSC if it's reliable. */
  129. if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable())
  130. tsc_speed = tsc_khz;
  131. else
  132. tsc_speed = 0;
  133. lg->lguest_data = (struct lguest_data __user *)lg->regs->edx;
  134. /* We check here so we can simply copy_to_user/from_user */
  135. if (!lguest_address_ok(lg, lg->regs->edx, sizeof(*lg->lguest_data))) {
  136. kill_guest(lg, "bad guest page %p", lg->lguest_data);
  137. return;
  138. }
  139. if (get_user(lg->noirq_start, &lg->lguest_data->noirq_start)
  140. || get_user(lg->noirq_end, &lg->lguest_data->noirq_end)
  141. /* We reserve the top pgd entry. */
  142. || put_user(4U*1024*1024, &lg->lguest_data->reserve_mem)
  143. || put_user(tsc_speed, &lg->lguest_data->tsc_khz)
  144. || put_user(lg->guestid, &lg->lguest_data->guestid))
  145. kill_guest(lg, "bad guest page %p", lg->lguest_data);
  146. /* This is the one case where the above accesses might have
  147. * been the first write to a Guest page. This may have caused
  148. * a copy-on-write fault, but the Guest might be referring to
  149. * the old (read-only) page. */
  150. guest_pagetable_clear_all(lg);
  151. }
  152. /* Even if we go out to userspace and come back, we don't want to do
  153. * the hypercall again. */
  154. static void clear_hcall(struct lguest *lg)
  155. {
  156. lg->regs->trapnum = 255;
  157. }
  158. void do_hypercalls(struct lguest *lg)
  159. {
  160. if (unlikely(!lg->lguest_data)) {
  161. if (lg->regs->trapnum == LGUEST_TRAP_ENTRY) {
  162. initialize(lg);
  163. clear_hcall(lg);
  164. }
  165. return;
  166. }
  167. do_async_hcalls(lg);
  168. if (!lg->dma_is_pending && lg->regs->trapnum == LGUEST_TRAP_ENTRY) {
  169. do_hcall(lg, lg->regs);
  170. clear_hcall(lg);
  171. }
  172. }