diff options
author | Glauber de Oliveira Costa <gcosta@redhat.com> | 2008-01-07 08:05:29 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-01-30 06:50:09 -0500 |
commit | 177e449dc5bd4cf8dc48d66abee61ddf34b126b9 (patch) | |
tree | f0aaea9407971d8f6b9ad4e177a834f1be3aa993 | |
parent | ad8d8f3bc61ec712dd141e1029ae68c47fadc4a7 (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.c | 2 | ||||
-rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 24 | ||||
-rw-r--r-- | drivers/lguest/lg.h | 10 | ||||
-rw-r--r-- | drivers/lguest/lguest_user.c | 8 | ||||
-rw-r--r-- | drivers/lguest/x86/core.c | 2 |
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). */ |
63 | static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err) | 63 | static 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. */ |
132 | void maybe_do_interrupt(struct lguest *lg) | 133 | void 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. */ |
248 | int deliver_trap(struct lguest *lg, unsigned int num) | 250 | int 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 | ||
105 | extern struct mutex lguest_lock; | 105 | extern 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: */ |
139 | void maybe_do_interrupt(struct lguest *lg); | 139 | void maybe_do_interrupt(struct lg_cpu *cpu); |
140 | int deliver_trap(struct lguest *lg, unsigned int num); | 140 | int deliver_trap(struct lg_cpu *cpu, unsigned int num); |
141 | void load_guest_idt_entry(struct lguest *lg, unsigned int i, u32 low, u32 hi); | 141 | void load_guest_idt_entry(struct lguest *lg, unsigned int i, u32 low, u32 hi); |
142 | void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages); | 142 | void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages); |
143 | void pin_stack_pages(struct lguest *lg); | 143 | void 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. */ |
39 | static int user_send_irq(struct lguest *lg, const unsigned long __user *input) | 39 | static 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. */ |