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>
This commit is contained in:
@@ -213,6 +213,20 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
|
|||||||
if (!more)
|
if (!more)
|
||||||
put_user(0, &cpu->lg->lguest_data->irq_pending);
|
put_user(0, &cpu->lg->lguest_data->irq_pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* And this is the routine when we want to set an interrupt for the Guest. */
|
||||||
|
void set_interrupt(struct lg_cpu *cpu, unsigned int irq)
|
||||||
|
{
|
||||||
|
/* Next time the Guest runs, the core code will see if it can deliver
|
||||||
|
* this interrupt. */
|
||||||
|
set_bit(irq, cpu->irqs_pending);
|
||||||
|
|
||||||
|
/* Make sure it sees it; it might be asleep (eg. halted), or
|
||||||
|
* running the Guest right now, in which case kick_process()
|
||||||
|
* will knock it out. */
|
||||||
|
if (!wake_up_process(cpu->tsk))
|
||||||
|
kick_process(cpu->tsk);
|
||||||
|
}
|
||||||
/*:*/
|
/*:*/
|
||||||
|
|
||||||
/* Linux uses trap 128 for system calls. Plan9 uses 64, and Ron Minnich sent
|
/* 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)
|
|||||||
struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
|
struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
|
||||||
|
|
||||||
/* Remember the first interrupt is the timer interrupt. */
|
/* Remember the first interrupt is the timer interrupt. */
|
||||||
set_bit(0, cpu->irqs_pending);
|
set_interrupt(cpu, 0);
|
||||||
/* Guest may be stopped or running on another CPU. */
|
|
||||||
if (!wake_up_process(cpu->tsk))
|
|
||||||
kick_process(cpu->tsk);
|
|
||||||
return HRTIMER_NORESTART;
|
return HRTIMER_NORESTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -143,6 +143,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user);
|
|||||||
/* interrupts_and_traps.c: */
|
/* interrupts_and_traps.c: */
|
||||||
unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more);
|
unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more);
|
||||||
void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more);
|
void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more);
|
||||||
|
void set_interrupt(struct lg_cpu *cpu, unsigned int irq);
|
||||||
bool deliver_trap(struct lg_cpu *cpu, unsigned int num);
|
bool deliver_trap(struct lg_cpu *cpu, unsigned int num);
|
||||||
void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i,
|
void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i,
|
||||||
u32 low, u32 hi);
|
u32 low, u32 hi);
|
||||||
|
@@ -45,9 +45,8 @@ static int user_send_irq(struct lg_cpu *cpu, const unsigned long __user *input)
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (irq >= LGUEST_IRQS)
|
if (irq >= LGUEST_IRQS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
/* Next time the Guest runs, the core code will see if it can deliver
|
|
||||||
* this interrupt. */
|
set_interrupt(cpu, irq);
|
||||||
set_bit(irq, cpu->irqs_pending);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,11 +251,6 @@ static ssize_t write(struct file *file, const char __user *in,
|
|||||||
/* Once the Guest is dead, you can only read() why it died. */
|
/* Once the Guest is dead, you can only read() why it died. */
|
||||||
if (lg->dead)
|
if (lg->dead)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/* If you're not the task which owns the Guest, all you can do
|
|
||||||
* is break the Launcher out of running the Guest. */
|
|
||||||
if (current != cpu->tsk && req != LHREQ_BREAK)
|
|
||||||
return -EPERM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (req) {
|
switch (req) {
|
||||||
|
Reference in New Issue
Block a user