diff options
author | David S. Miller <davem@davemloft.net> | 2009-06-15 06:02:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-15 06:02:23 -0400 |
commit | 9cbc1cb8cd46ce1f7645b9de249b2ce8460129bb (patch) | |
tree | 8d104ec2a459346b99413b0b77421ca7b9936c1a /drivers/lguest/interrupts_and_traps.c | |
parent | ca44d6e60f9de26281fda203f58b570e1748c015 (diff) | |
parent | 45e3e1935e2857c54783291107d33323b3ef33c8 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
Documentation/feature-removal-schedule.txt
drivers/scsi/fcoe/fcoe.c
net/core/drop_monitor.c
net/core/net-traces.c
Diffstat (limited to 'drivers/lguest/interrupts_and_traps.c')
-rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 6e99adbe1946..0e9067b0d507 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c | |||
@@ -128,30 +128,39 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, | |||
128 | /*H:205 | 128 | /*H:205 |
129 | * Virtual Interrupts. | 129 | * Virtual Interrupts. |
130 | * | 130 | * |
131 | * maybe_do_interrupt() gets called before every entry to the Guest, to see if | 131 | * interrupt_pending() returns the first pending interrupt which isn't blocked |
132 | * we should divert the Guest to running an interrupt handler. */ | 132 | * by the Guest. It is called before every entry to the Guest, and just before |
133 | void maybe_do_interrupt(struct lg_cpu *cpu) | 133 | * we go to sleep when the Guest has halted itself. */ |
134 | unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more) | ||
134 | { | 135 | { |
135 | unsigned int irq; | 136 | unsigned int irq; |
136 | DECLARE_BITMAP(blk, LGUEST_IRQS); | 137 | DECLARE_BITMAP(blk, LGUEST_IRQS); |
137 | struct desc_struct *idt; | ||
138 | 138 | ||
139 | /* If the Guest hasn't even initialized yet, we can do nothing. */ | 139 | /* If the Guest hasn't even initialized yet, we can do nothing. */ |
140 | if (!cpu->lg->lguest_data) | 140 | if (!cpu->lg->lguest_data) |
141 | return; | 141 | return LGUEST_IRQS; |
142 | 142 | ||
143 | /* Take our "irqs_pending" array and remove any interrupts the Guest | 143 | /* Take our "irqs_pending" array and remove any interrupts the Guest |
144 | * wants blocked: the result ends up in "blk". */ | 144 | * wants blocked: the result ends up in "blk". */ |
145 | if (copy_from_user(&blk, cpu->lg->lguest_data->blocked_interrupts, | 145 | if (copy_from_user(&blk, cpu->lg->lguest_data->blocked_interrupts, |
146 | sizeof(blk))) | 146 | sizeof(blk))) |
147 | return; | 147 | return LGUEST_IRQS; |
148 | bitmap_andnot(blk, cpu->irqs_pending, blk, LGUEST_IRQS); | 148 | bitmap_andnot(blk, cpu->irqs_pending, blk, LGUEST_IRQS); |
149 | 149 | ||
150 | /* Find the first interrupt. */ | 150 | /* Find the first interrupt. */ |
151 | irq = find_first_bit(blk, LGUEST_IRQS); | 151 | irq = find_first_bit(blk, LGUEST_IRQS); |
152 | /* None? Nothing to do */ | 152 | *more = find_next_bit(blk, LGUEST_IRQS, irq+1); |
153 | if (irq >= LGUEST_IRQS) | 153 | |
154 | return; | 154 | return irq; |
155 | } | ||
156 | |||
157 | /* This actually diverts the Guest to running an interrupt handler, once an | ||
158 | * interrupt has been identified by interrupt_pending(). */ | ||
159 | void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more) | ||
160 | { | ||
161 | struct desc_struct *idt; | ||
162 | |||
163 | BUG_ON(irq >= LGUEST_IRQS); | ||
155 | 164 | ||
156 | /* They may be in the middle of an iret, where they asked us never to | 165 | /* They may be in the middle of an iret, where they asked us never to |
157 | * deliver interrupts. */ | 166 | * deliver interrupts. */ |
@@ -170,8 +179,12 @@ void maybe_do_interrupt(struct lg_cpu *cpu) | |||
170 | u32 irq_enabled; | 179 | u32 irq_enabled; |
171 | if (get_user(irq_enabled, &cpu->lg->lguest_data->irq_enabled)) | 180 | if (get_user(irq_enabled, &cpu->lg->lguest_data->irq_enabled)) |
172 | irq_enabled = 0; | 181 | irq_enabled = 0; |
173 | if (!irq_enabled) | 182 | if (!irq_enabled) { |
183 | /* Make sure they know an IRQ is pending. */ | ||
184 | put_user(X86_EFLAGS_IF, | ||
185 | &cpu->lg->lguest_data->irq_pending); | ||
174 | return; | 186 | return; |
187 | } | ||
175 | } | 188 | } |
176 | 189 | ||
177 | /* Look at the IDT entry the Guest gave us for this interrupt. The | 190 | /* Look at the IDT entry the Guest gave us for this interrupt. The |
@@ -194,6 +207,25 @@ void maybe_do_interrupt(struct lg_cpu *cpu) | |||
194 | * here is a compromise which means at least it gets updated every | 207 | * here is a compromise which means at least it gets updated every |
195 | * timer interrupt. */ | 208 | * timer interrupt. */ |
196 | write_timestamp(cpu); | 209 | write_timestamp(cpu); |
210 | |||
211 | /* If there are no other interrupts we want to deliver, clear | ||
212 | * the pending flag. */ | ||
213 | if (!more) | ||
214 | put_user(0, &cpu->lg->lguest_data->irq_pending); | ||
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); | ||
197 | } | 229 | } |
198 | /*:*/ | 230 | /*:*/ |
199 | 231 | ||
@@ -510,10 +542,7 @@ static enum hrtimer_restart clockdev_fn(struct hrtimer *timer) | |||
510 | struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt); | 542 | struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt); |
511 | 543 | ||
512 | /* Remember the first interrupt is the timer interrupt. */ | 544 | /* Remember the first interrupt is the timer interrupt. */ |
513 | set_bit(0, cpu->irqs_pending); | 545 | set_interrupt(cpu, 0); |
514 | /* If the Guest is actually stopped, we need to wake it up. */ | ||
515 | if (cpu->halted) | ||
516 | wake_up_process(cpu->tsk); | ||
517 | return HRTIMER_NORESTART; | 546 | return HRTIMER_NORESTART; |
518 | } | 547 | } |
519 | 548 | ||