aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlauber de Oliveira Costa <gcosta@redhat.com>2008-01-07 08:05:29 -0500
committerRusty Russell <rusty@rustcorp.com.au>2008-01-30 06:50:09 -0500
commit177e449dc5bd4cf8dc48d66abee61ddf34b126b9 (patch)
treef0aaea9407971d8f6b9ad4e177a834f1be3aa993
parentad8d8f3bc61ec712dd141e1029ae68c47fadc4a7 (diff)
lguest: per-vcpu interrupt processing.
This patch adapts interrupt processing for using the vcpu struct. Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/lguest/core.c2
-rw-r--r--drivers/lguest/interrupts_and_traps.c24
-rw-r--r--drivers/lguest/lg.h10
-rw-r--r--drivers/lguest/lguest_user.c8
-rw-r--r--drivers/lguest/x86/core.c2
5 files changed, 24 insertions, 22 deletions
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 0ea67cb0cc0b..d8e1ac305dc6 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -203,7 +203,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
203 /* Check if there are any interrupts which can be delivered 203 /* Check if there are any interrupts which can be delivered
204 * now: if so, this sets up the hander to be executed when we 204 * now: if so, this sets up the hander to be executed when we
205 * next run the Guest. */ 205 * next run the Guest. */
206 maybe_do_interrupt(lg); 206 maybe_do_interrupt(cpu);
207 207
208 /* All long-lived kernel loops need to check with this horrible 208 /* All long-lived kernel loops need to check with this horrible
209 * thing called the freezer. If the Host is trying to suspend, 209 * thing called the freezer. If the Host is trying to suspend,
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 22c692aae51c..8f59232f458b 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -60,11 +60,12 @@ static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val)
60 * We set up the stack just like the CPU does for a real interrupt, so it's 60 * We set up the stack just like the CPU does for a real interrupt, so it's
61 * identical for the Guest (and the standard "iret" instruction will undo 61 * identical for the Guest (and the standard "iret" instruction will undo
62 * it). */ 62 * it). */
63static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err) 63static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
64{ 64{
65 unsigned long gstack, origstack; 65 unsigned long gstack, origstack;
66 u32 eflags, ss, irq_enable; 66 u32 eflags, ss, irq_enable;
67 unsigned long virtstack; 67 unsigned long virtstack;
68 struct lguest *lg = cpu->lg;
68 69
69 /* There are two cases for interrupts: one where the Guest is already 70 /* There are two cases for interrupts: one where the Guest is already
70 * in the kernel, and a more complex one where the Guest is in 71 * in the kernel, and a more complex one where the Guest is in
@@ -129,9 +130,10 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
129 * 130 *
130 * maybe_do_interrupt() gets called before every entry to the Guest, to see if 131 * maybe_do_interrupt() gets called before every entry to the Guest, to see if
131 * we should divert the Guest to running an interrupt handler. */ 132 * we should divert the Guest to running an interrupt handler. */
132void maybe_do_interrupt(struct lguest *lg) 133void maybe_do_interrupt(struct lg_cpu *cpu)
133{ 134{
134 unsigned int irq; 135 unsigned int irq;
136 struct lguest *lg = cpu->lg;
135 DECLARE_BITMAP(blk, LGUEST_IRQS); 137 DECLARE_BITMAP(blk, LGUEST_IRQS);
136 struct desc_struct *idt; 138 struct desc_struct *idt;
137 139
@@ -145,7 +147,7 @@ void maybe_do_interrupt(struct lguest *lg)
145 sizeof(blk))) 147 sizeof(blk)))
146 return; 148 return;
147 149
148 bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS); 150 bitmap_andnot(blk, cpu->irqs_pending, blk, LGUEST_IRQS);
149 151
150 /* Find the first interrupt. */ 152 /* Find the first interrupt. */
151 irq = find_first_bit(blk, LGUEST_IRQS); 153 irq = find_first_bit(blk, LGUEST_IRQS);
@@ -180,11 +182,11 @@ void maybe_do_interrupt(struct lguest *lg)
180 /* If they don't have a handler (yet?), we just ignore it */ 182 /* If they don't have a handler (yet?), we just ignore it */
181 if (idt_present(idt->a, idt->b)) { 183 if (idt_present(idt->a, idt->b)) {
182 /* OK, mark it no longer pending and deliver it. */ 184 /* OK, mark it no longer pending and deliver it. */
183 clear_bit(irq, lg->irqs_pending); 185 clear_bit(irq, cpu->irqs_pending);
184 /* set_guest_interrupt() takes the interrupt descriptor and a 186 /* set_guest_interrupt() takes the interrupt descriptor and a
185 * flag to say whether this interrupt pushes an error code onto 187 * flag to say whether this interrupt pushes an error code onto
186 * the stack as well: virtual interrupts never do. */ 188 * the stack as well: virtual interrupts never do. */
187 set_guest_interrupt(lg, idt->a, idt->b, 0); 189 set_guest_interrupt(cpu, idt->a, idt->b, 0);
188 } 190 }
189 191
190 /* Every time we deliver an interrupt, we update the timestamp in the 192 /* Every time we deliver an interrupt, we update the timestamp in the
@@ -245,19 +247,19 @@ static int has_err(unsigned int trap)
245} 247}
246 248
247/* deliver_trap() returns true if it could deliver the trap. */ 249/* deliver_trap() returns true if it could deliver the trap. */
248int deliver_trap(struct lguest *lg, unsigned int num) 250int deliver_trap(struct lg_cpu *cpu, unsigned int num)
249{ 251{
250 /* Trap numbers are always 8 bit, but we set an impossible trap number 252 /* Trap numbers are always 8 bit, but we set an impossible trap number
251 * for traps inside the Switcher, so check that here. */ 253 * for traps inside the Switcher, so check that here. */
252 if (num >= ARRAY_SIZE(lg->arch.idt)) 254 if (num >= ARRAY_SIZE(cpu->lg->arch.idt))
253 return 0; 255 return 0;
254 256
255 /* Early on the Guest hasn't set the IDT entries (or maybe it put a 257 /* Early on the Guest hasn't set the IDT entries (or maybe it put a
256 * bogus one in): if we fail here, the Guest will be killed. */ 258 * bogus one in): if we fail here, the Guest will be killed. */
257 if (!idt_present(lg->arch.idt[num].a, lg->arch.idt[num].b)) 259 if (!idt_present(cpu->lg->arch.idt[num].a, cpu->lg->arch.idt[num].b))
258 return 0; 260 return 0;
259 set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b, 261 set_guest_interrupt(cpu, cpu->lg->arch.idt[num].a,
260 has_err(num)); 262 cpu->lg->arch.idt[num].b, has_err(num));
261 return 1; 263 return 1;
262} 264}
263 265
@@ -493,7 +495,7 @@ static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
493 struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt); 495 struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
494 496
495 /* Remember the first interrupt is the timer interrupt. */ 497 /* Remember the first interrupt is the timer interrupt. */
496 set_bit(0, cpu->lg->irqs_pending); 498 set_bit(0, cpu->irqs_pending);
497 /* If the Guest is actually stopped, we need to wake it up. */ 499 /* If the Guest is actually stopped, we need to wake it up. */
498 if (cpu->lg->halted) 500 if (cpu->lg->halted)
499 wake_up_process(cpu->lg->tsk); 501 wake_up_process(cpu->lg->tsk);
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 7da7b3f68da8..29e03d588a8d 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -50,6 +50,9 @@ struct lg_cpu {
50 50
51 /* Virtual clock device */ 51 /* Virtual clock device */
52 struct hrtimer hrt; 52 struct hrtimer hrt;
53
54 /* Pending virtual interrupts */
55 DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
53}; 56};
54 57
55/* The private info the thread maintains about the guest. */ 58/* The private info the thread maintains about the guest. */
@@ -97,9 +100,6 @@ struct lguest
97 const char *dead; 100 const char *dead;
98 101
99 struct lguest_arch arch; 102 struct lguest_arch arch;
100
101 /* Pending virtual interrupts */
102 DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
103}; 103};
104 104
105extern struct mutex lguest_lock; 105extern struct mutex lguest_lock;
@@ -136,8 +136,8 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user);
136#define pgd_pfn(x) (pgd_val(x) >> PAGE_SHIFT) 136#define pgd_pfn(x) (pgd_val(x) >> PAGE_SHIFT)
137 137
138/* interrupts_and_traps.c: */ 138/* interrupts_and_traps.c: */
139void maybe_do_interrupt(struct lguest *lg); 139void maybe_do_interrupt(struct lg_cpu *cpu);
140int deliver_trap(struct lguest *lg, unsigned int num); 140int deliver_trap(struct lg_cpu *cpu, unsigned int num);
141void load_guest_idt_entry(struct lguest *lg, unsigned int i, u32 low, u32 hi); 141void load_guest_idt_entry(struct lguest *lg, unsigned int i, u32 low, u32 hi);
142void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages); 142void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages);
143void pin_stack_pages(struct lguest *lg); 143void pin_stack_pages(struct lguest *lg);
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index f231b9be0b64..605db5c49e7f 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -36,7 +36,7 @@ static int break_guest_out(struct lguest *lg, const unsigned long __user *input)
36 36
37/*L:050 Sending an interrupt is done by writing LHREQ_IRQ and an interrupt 37/*L:050 Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
38 * number to /dev/lguest. */ 38 * number to /dev/lguest. */
39static int user_send_irq(struct lguest *lg, const unsigned long __user *input) 39static int user_send_irq(struct lg_cpu *cpu, const unsigned long __user *input)
40{ 40{
41 unsigned long irq; 41 unsigned long irq;
42 42
@@ -46,7 +46,7 @@ static int user_send_irq(struct lguest *lg, const unsigned long __user *input)
46 return -EINVAL; 46 return -EINVAL;
47 /* Next time the Guest runs, the core code will see if it can deliver 47 /* Next time the Guest runs, the core code will see if it can deliver
48 * this interrupt. */ 48 * this interrupt. */
49 set_bit(irq, lg->irqs_pending); 49 set_bit(irq, cpu->irqs_pending);
50 return 0; 50 return 0;
51} 51}
52 52
@@ -225,7 +225,7 @@ static ssize_t write(struct file *file, const char __user *in,
225 struct lguest *lg = file->private_data; 225 struct lguest *lg = file->private_data;
226 const unsigned long __user *input = (const unsigned long __user *)in; 226 const unsigned long __user *input = (const unsigned long __user *)in;
227 unsigned long req; 227 unsigned long req;
228 struct lg_cpu *cpu; 228 struct lg_cpu *uninitialized_var(cpu);
229 unsigned int cpu_id = *off; 229 unsigned int cpu_id = *off;
230 230
231 if (get_user(req, input) != 0) 231 if (get_user(req, input) != 0)
@@ -253,7 +253,7 @@ static ssize_t write(struct file *file, const char __user *in,
253 case LHREQ_INITIALIZE: 253 case LHREQ_INITIALIZE:
254 return initialize(file, input); 254 return initialize(file, input);
255 case LHREQ_IRQ: 255 case LHREQ_IRQ:
256 return user_send_irq(lg, input); 256 return user_send_irq(cpu, input);
257 case LHREQ_BREAK: 257 case LHREQ_BREAK:
258 return break_guest_out(lg, input); 258 return break_guest_out(lg, input);
259 default: 259 default:
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 5962160aff3d..66f48fcc1196 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -342,7 +342,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
342 } 342 }
343 343
344 /* We didn't handle the trap, so it needs to go to the Guest. */ 344 /* We didn't handle the trap, so it needs to go to the Guest. */
345 if (!deliver_trap(lg, lg->regs->trapnum)) 345 if (!deliver_trap(cpu, lg->regs->trapnum))
346 /* If the Guest doesn't have a handler (either it hasn't 346 /* If the Guest doesn't have a handler (either it hasn't
347 * registered any yet, or it's one of the faults we don't let 347 * registered any yet, or it's one of the faults we don't let
348 * it handle), it dies with a cryptic error message. */ 348 * it handle), it dies with a cryptic error message. */