diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2009-06-13 00:27:08 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2009-06-12 08:57:09 -0400 |
commit | 9f155a9b3d5a5444bcc5e049ec2547bb5107150e (patch) | |
tree | ef8fe2d5a319abb3bb1c89374f9d2fef1b0881c3 | |
parent | 92b4d8df8436cdd74d22a2a5b6b23b9abc737a3e (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>
-rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 19 | ||||
-rw-r--r-- | drivers/lguest/lg.h | 1 | ||||
-rw-r--r-- | drivers/lguest/lguest_user.c | 10 |
3 files changed, 18 insertions, 12 deletions
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 5a10754b4790..0e9067b0d507 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. */ | ||
218 | void 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 6201ce59e886..040cb70780e7 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: */ |
144 | unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more); | 144 | unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more); |
145 | void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more); | 145 | void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more); |
146 | void set_interrupt(struct lg_cpu *cpu, unsigned int irq); | ||
146 | bool deliver_trap(struct lg_cpu *cpu, unsigned int num); | 147 | bool deliver_trap(struct lg_cpu *cpu, unsigned int num); |
147 | void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i, | 148 | void 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 bcdcf3453e78..1982b45bd935 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) { |