lguest_user.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* Userspace control of the guest, via /dev/lguest. */
  2. #include <linux/uaccess.h>
  3. #include <linux/miscdevice.h>
  4. #include <linux/fs.h>
  5. #include "lg.h"
  6. static void setup_regs(struct lguest_regs *regs, unsigned long start)
  7. {
  8. /* Write out stack in format lguest expects, so we can switch to it. */
  9. regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL;
  10. regs->cs = __KERNEL_CS|GUEST_PL;
  11. regs->eflags = 0x202; /* Interrupts enabled. */
  12. regs->eip = start;
  13. /* esi points to our boot information (physical address 0) */
  14. }
  15. /* + addr */
  16. static long user_get_dma(struct lguest *lg, const u32 __user *input)
  17. {
  18. unsigned long key, udma, irq;
  19. if (get_user(key, input) != 0)
  20. return -EFAULT;
  21. udma = get_dma_buffer(lg, key, &irq);
  22. if (!udma)
  23. return -ENOENT;
  24. /* We put irq number in udma->used_len. */
  25. lgwrite_u32(lg, udma + offsetof(struct lguest_dma, used_len), irq);
  26. return udma;
  27. }
  28. /* To force the Guest to stop running and return to the Launcher, the
  29. * Waker sets writes LHREQ_BREAK and the value "1" to /dev/lguest. The
  30. * Launcher then writes LHREQ_BREAK and "0" to release the Waker. */
  31. static int break_guest_out(struct lguest *lg, const u32 __user *input)
  32. {
  33. unsigned long on;
  34. /* Fetch whether they're turning break on or off.. */
  35. if (get_user(on, input) != 0)
  36. return -EFAULT;
  37. if (on) {
  38. lg->break_out = 1;
  39. /* Pop it out (may be running on different CPU) */
  40. wake_up_process(lg->tsk);
  41. /* Wait for them to reset it */
  42. return wait_event_interruptible(lg->break_wq, !lg->break_out);
  43. } else {
  44. lg->break_out = 0;
  45. wake_up(&lg->break_wq);
  46. return 0;
  47. }
  48. }
  49. /* + irq */
  50. static int user_send_irq(struct lguest *lg, const u32 __user *input)
  51. {
  52. u32 irq;
  53. if (get_user(irq, input) != 0)
  54. return -EFAULT;
  55. if (irq >= LGUEST_IRQS)
  56. return -EINVAL;
  57. set_bit(irq, lg->irqs_pending);
  58. return 0;
  59. }
  60. static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
  61. {
  62. struct lguest *lg = file->private_data;
  63. if (!lg)
  64. return -EINVAL;
  65. /* If you're not the task which owns the guest, go away. */
  66. if (current != lg->tsk)
  67. return -EPERM;
  68. if (lg->dead) {
  69. size_t len;
  70. if (IS_ERR(lg->dead))
  71. return PTR_ERR(lg->dead);
  72. len = min(size, strlen(lg->dead)+1);
  73. if (copy_to_user(user, lg->dead, len) != 0)
  74. return -EFAULT;
  75. return len;
  76. }
  77. if (lg->dma_is_pending)
  78. lg->dma_is_pending = 0;
  79. return run_guest(lg, (unsigned long __user *)user);
  80. }
  81. /* Take: pfnlimit, pgdir, start, pageoffset. */
  82. static int initialize(struct file *file, const u32 __user *input)
  83. {
  84. struct lguest *lg;
  85. int err, i;
  86. u32 args[4];
  87. /* We grab the Big Lguest lock, which protects the global array
  88. * "lguests" and multiple simultaneous initializations. */
  89. mutex_lock(&lguest_lock);
  90. if (file->private_data) {
  91. err = -EBUSY;
  92. goto unlock;
  93. }
  94. if (copy_from_user(args, input, sizeof(args)) != 0) {
  95. err = -EFAULT;
  96. goto unlock;
  97. }
  98. i = find_free_guest();
  99. if (i < 0) {
  100. err = -ENOSPC;
  101. goto unlock;
  102. }
  103. lg = &lguests[i];
  104. lg->guestid = i;
  105. lg->pfn_limit = args[0];
  106. lg->page_offset = args[3];
  107. lg->regs_page = get_zeroed_page(GFP_KERNEL);
  108. if (!lg->regs_page) {
  109. err = -ENOMEM;
  110. goto release_guest;
  111. }
  112. lg->regs = (void *)lg->regs_page + PAGE_SIZE - sizeof(*lg->regs);
  113. err = init_guest_pagetable(lg, args[1]);
  114. if (err)
  115. goto free_regs;
  116. setup_regs(lg->regs, args[2]);
  117. setup_guest_gdt(lg);
  118. init_clockdev(lg);
  119. lg->tsk = current;
  120. lg->mm = get_task_mm(lg->tsk);
  121. init_waitqueue_head(&lg->break_wq);
  122. lg->last_pages = NULL;
  123. file->private_data = lg;
  124. mutex_unlock(&lguest_lock);
  125. return sizeof(args);
  126. free_regs:
  127. free_page(lg->regs_page);
  128. release_guest:
  129. memset(lg, 0, sizeof(*lg));
  130. unlock:
  131. mutex_unlock(&lguest_lock);
  132. return err;
  133. }
  134. static ssize_t write(struct file *file, const char __user *input,
  135. size_t size, loff_t *off)
  136. {
  137. struct lguest *lg = file->private_data;
  138. u32 req;
  139. if (get_user(req, input) != 0)
  140. return -EFAULT;
  141. input += sizeof(req);
  142. if (req != LHREQ_INITIALIZE && !lg)
  143. return -EINVAL;
  144. if (lg && lg->dead)
  145. return -ENOENT;
  146. /* If you're not the task which owns the Guest, you can only break */
  147. if (lg && current != lg->tsk && req != LHREQ_BREAK)
  148. return -EPERM;
  149. switch (req) {
  150. case LHREQ_INITIALIZE:
  151. return initialize(file, (const u32 __user *)input);
  152. case LHREQ_GETDMA:
  153. return user_get_dma(lg, (const u32 __user *)input);
  154. case LHREQ_IRQ:
  155. return user_send_irq(lg, (const u32 __user *)input);
  156. case LHREQ_BREAK:
  157. return break_guest_out(lg, (const u32 __user *)input);
  158. default:
  159. return -EINVAL;
  160. }
  161. }
  162. static int close(struct inode *inode, struct file *file)
  163. {
  164. struct lguest *lg = file->private_data;
  165. if (!lg)
  166. return 0;
  167. mutex_lock(&lguest_lock);
  168. /* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
  169. hrtimer_cancel(&lg->hrt);
  170. release_all_dma(lg);
  171. free_guest_pagetable(lg);
  172. mmput(lg->mm);
  173. if (!IS_ERR(lg->dead))
  174. kfree(lg->dead);
  175. free_page(lg->regs_page);
  176. memset(lg, 0, sizeof(*lg));
  177. mutex_unlock(&lguest_lock);
  178. return 0;
  179. }
  180. static struct file_operations lguest_fops = {
  181. .owner = THIS_MODULE,
  182. .release = close,
  183. .write = write,
  184. .read = read,
  185. };
  186. static struct miscdevice lguest_dev = {
  187. .minor = MISC_DYNAMIC_MINOR,
  188. .name = "lguest",
  189. .fops = &lguest_fops,
  190. };
  191. int __init lguest_device_init(void)
  192. {
  193. return misc_register(&lguest_dev);
  194. }
  195. void __exit lguest_device_remove(void)
  196. {
  197. misc_deregister(&lguest_dev);
  198. }