1 /* Userspace control of the guest, via /dev/lguest. */
2 #include <linux/uaccess.h>
3 #include <linux/miscdevice.h>
7 static void setup_regs(struct lguest_regs *regs, unsigned long start)
9 /* Write out stack in format lguest expects, so we can switch to it. */
10 regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL;
11 regs->cs = __KERNEL_CS|GUEST_PL;
12 regs->eflags = 0x202; /* Interrupts enabled. */
14 /* esi points to our boot information (physical address 0) */
18 static long user_get_dma(struct lguest *lg, const u32 __user *input)
20 unsigned long key, udma, irq;
22 if (get_user(key, input) != 0)
24 udma = get_dma_buffer(lg, key, &irq);
28 /* We put irq number in udma->used_len. */
29 lgwrite_u32(lg, udma + offsetof(struct lguest_dma, used_len), irq);
33 /* To force the Guest to stop running and return to the Launcher, the
34 * Waker sets writes LHREQ_BREAK and the value "1" to /dev/lguest. The
35 * Launcher then writes LHREQ_BREAK and "0" to release the Waker. */
36 static int break_guest_out(struct lguest *lg, const u32 __user *input)
40 /* Fetch whether they're turning break on or off.. */
41 if (get_user(on, input) != 0)
46 /* Pop it out (may be running on different CPU) */
47 wake_up_process(lg->tsk);
48 /* Wait for them to reset it */
49 return wait_event_interruptible(lg->break_wq, !lg->break_out);
52 wake_up(&lg->break_wq);
58 static int user_send_irq(struct lguest *lg, const u32 __user *input)
62 if (get_user(irq, input) != 0)
64 if (irq >= LGUEST_IRQS)
66 set_bit(irq, lg->irqs_pending);
70 static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
72 struct lguest *lg = file->private_data;
77 /* If you're not the task which owns the guest, go away. */
78 if (current != lg->tsk)
85 return PTR_ERR(lg->dead);
87 len = min(size, strlen(lg->dead)+1);
88 if (copy_to_user(user, lg->dead, len) != 0)
93 if (lg->dma_is_pending)
94 lg->dma_is_pending = 0;
96 return run_guest(lg, (unsigned long __user *)user);
99 /* Take: pfnlimit, pgdir, start, pageoffset. */
100 static int initialize(struct file *file, const u32 __user *input)
106 /* We grab the Big Lguest lock, which protects the global array
107 * "lguests" and multiple simultaneous initializations. */
108 mutex_lock(&lguest_lock);
110 if (file->private_data) {
115 if (copy_from_user(args, input, sizeof(args)) != 0) {
120 i = find_free_guest();
127 lg->pfn_limit = args[0];
128 lg->page_offset = args[3];
129 lg->regs_page = get_zeroed_page(GFP_KERNEL);
130 if (!lg->regs_page) {
134 lg->regs = (void *)lg->regs_page + PAGE_SIZE - sizeof(*lg->regs);
136 err = init_guest_pagetable(lg, args[1]);
140 setup_regs(lg->regs, args[2]);
144 lg->mm = get_task_mm(lg->tsk);
145 init_waitqueue_head(&lg->break_wq);
146 lg->last_pages = NULL;
147 file->private_data = lg;
149 mutex_unlock(&lguest_lock);
154 free_page(lg->regs_page);
156 memset(lg, 0, sizeof(*lg));
158 mutex_unlock(&lguest_lock);
162 static ssize_t write(struct file *file, const char __user *input,
163 size_t size, loff_t *off)
165 struct lguest *lg = file->private_data;
168 if (get_user(req, input) != 0)
170 input += sizeof(req);
172 if (req != LHREQ_INITIALIZE && !lg)
177 /* If you're not the task which owns the Guest, you can only break */
178 if (lg && current != lg->tsk && req != LHREQ_BREAK)
182 case LHREQ_INITIALIZE:
183 return initialize(file, (const u32 __user *)input);
185 return user_get_dma(lg, (const u32 __user *)input);
187 return user_send_irq(lg, (const u32 __user *)input);
189 return break_guest_out(lg, (const u32 __user *)input);
195 static int close(struct inode *inode, struct file *file)
197 struct lguest *lg = file->private_data;
202 mutex_lock(&lguest_lock);
203 /* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
204 hrtimer_cancel(&lg->hrt);
206 free_guest_pagetable(lg);
208 if (!IS_ERR(lg->dead))
210 free_page(lg->regs_page);
211 memset(lg, 0, sizeof(*lg));
212 mutex_unlock(&lguest_lock);
216 static struct file_operations lguest_fops = {
217 .owner = THIS_MODULE,
222 static struct miscdevice lguest_dev = {
223 .minor = MISC_DYNAMIC_MINOR,
225 .fops = &lguest_fops,
228 int __init lguest_device_init(void)
230 return misc_register(&lguest_dev);
233 void __exit lguest_device_remove(void)
235 misc_deregister(&lguest_dev);