aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2009-06-13 00:27:08 -0400
committerRusty Russell <rusty@rustcorp.com.au>2009-06-12 08:57:09 -0400
commit9f155a9b3d5a5444bcc5e049ec2547bb5107150e (patch)
treeef8fe2d5a319abb3bb1c89374f9d2fef1b0881c3 /drivers
parent92b4d8df8436cdd74d22a2a5b6b23b9abc737a3e (diff)
lguest: allow any process to send interrupts
We currently only allow the Launcher process to send interrupts, but it as we already send interrupts from the hrtimer, it's a simple matter of extracting that code into a common set_interrupt routine. As we switch to a thread per virtqueue, this avoids a bottleneck through the main Launcher process. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/lguest/interrupts_and_traps.c19
-rw-r--r--drivers/lguest/lg.h1
-rw-r--r--drivers/lguest/lguest_user.c10
3 files changed, 18 insertions, 12 deletions
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 5a10754b479..0e9067b0d50 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -213,6 +213,20 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
213 if (!more) 213 if (!more)
214 put_user(0, &cpu->lg->lguest_data->irq_pending); 214 put_user(0, &cpu->lg->lguest_data->irq_pending);
215} 215}
216
217/* And this is the routine when we want to set an interrupt for the Guest. */
218void set_interrupt(struct lg_cpu *cpu, unsigned int irq)
219{
220 /* Next time the Guest runs, the core code will see if it can deliver
221 * this interrupt. */
222 set_bit(irq, cpu->irqs_pending);
223
224 /* Make sure it sees it; it might be asleep (eg. halted), or
225 * running the Guest right now, in which case kick_process()
226 * will knock it out. */
227 if (!wake_up_process(cpu->tsk))
228 kick_process(cpu->tsk);
229}
216/*:*/ 230/*:*/
217 231
218/* Linux uses trap 128 for system calls. Plan9 uses 64, and Ron Minnich sent 232/* Linux uses trap 128 for system calls. Plan9 uses 64, and Ron Minnich sent
@@ -528,10 +542,7 @@ static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
528 struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt); 542 struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
529 543
530 /* Remember the first interrupt is the timer interrupt. */ 544 /* Remember the first interrupt is the timer interrupt. */
531 set_bit(0, cpu->irqs_pending); 545 set_interrupt(cpu, 0);
532 /* Guest may be stopped or running on another CPU. */
533 if (!wake_up_process(cpu->tsk))
534 kick_process(cpu->tsk);
535 return HRTIMER_NORESTART; 546 return HRTIMER_NORESTART;
536} 547}
537 548
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 6201ce59e88..040cb70780e 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -143,6 +143,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user);
143/* interrupts_and_traps.c: */ 143/* interrupts_and_traps.c: */
144unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more); 144unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more);
145void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more); 145void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more);
146void set_interrupt(struct lg_cpu *cpu, unsigned int irq);
146bool deliver_trap(struct lg_cpu *cpu, unsigned int num); 147bool deliver_trap(struct lg_cpu *cpu, unsigned int num);
147void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i, 148void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i,
148 u32 low, u32 hi); 149 u32 low, u32 hi);
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index bcdcf3453e7..1982b45bd93 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -45,9 +45,8 @@ static int user_send_irq(struct lg_cpu *cpu, const unsigned long __user *input)
45 return -EFAULT; 45 return -EFAULT;
46 if (irq >= LGUEST_IRQS) 46 if (irq >= LGUEST_IRQS)
47 return -EINVAL; 47 return -EINVAL;
48 /* Next time the Guest runs, the core code will see if it can deliver 48
49 * this interrupt. */ 49 set_interrupt(cpu, irq);
50 set_bit(irq, cpu->irqs_pending);
51 return 0; 50 return 0;
52} 51}
53 52
@@ -252,11 +251,6 @@ static ssize_t write(struct file *file, const char __user *in,
252 /* Once the Guest is dead, you can only read() why it died. */ 251 /* Once the Guest is dead, you can only read() why it died. */
253 if (lg->dead) 252 if (lg->dead)
254 return -ENOENT; 253 return -ENOENT;
255
256 /* If you're not the task which owns the Guest, all you can do
257 * is break the Launcher out of running the Guest. */
258 if (current != cpu->tsk && req != LHREQ_BREAK)
259 return -EPERM;
260 } 254 }
261 255
262 switch (req) { 256 switch (req) {