aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/interrupts_and_traps.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-10-25 01:02:50 -0400
committerRusty Russell <rusty@rustcorp.com.au>2007-10-25 01:02:50 -0400
commite1e72965ec2c02db99b415cd06c17ea90767e3a4 (patch)
tree94e43aac35bdc33220e64f285b72b3b2b787fd57 /drivers/lguest/interrupts_and_traps.c
parent568a17ffce2eeceae0cd9fc37e97cbad12f70278 (diff)
lguest: documentation update
Went through the documentation doing typo and content fixes. This patch contains only comment and whitespace changes. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/lguest/interrupts_and_traps.c')
-rw-r--r--drivers/lguest/interrupts_and_traps.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 82966982cb3..2b66f79c208 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -92,8 +92,8 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
92 92
93 /* Remember that we never let the Guest actually disable interrupts, so 93 /* Remember that we never let the Guest actually disable interrupts, so
94 * the "Interrupt Flag" bit is always set. We copy that bit from the 94 * the "Interrupt Flag" bit is always set. We copy that bit from the
95 * Guest's "irq_enabled" field into the eflags word: the Guest copies 95 * Guest's "irq_enabled" field into the eflags word: we saw the Guest
96 * it back in "lguest_iret". */ 96 * copy it back in "lguest_iret". */
97 eflags = lg->regs->eflags; 97 eflags = lg->regs->eflags;
98 if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0 98 if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0
99 && !(irq_enable & X86_EFLAGS_IF)) 99 && !(irq_enable & X86_EFLAGS_IF))
@@ -124,7 +124,7 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
124 kill_guest(lg, "Disabling interrupts"); 124 kill_guest(lg, "Disabling interrupts");
125} 125}
126 126
127/*H:200 127/*H:205
128 * Virtual Interrupts. 128 * Virtual Interrupts.
129 * 129 *
130 * maybe_do_interrupt() gets called before every entry to the Guest, to see if 130 * maybe_do_interrupt() gets called before every entry to the Guest, to see if
@@ -256,19 +256,21 @@ int deliver_trap(struct lguest *lg, unsigned int num)
256 * bogus one in): if we fail here, the Guest will be killed. */ 256 * 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)) 257 if (!idt_present(lg->arch.idt[num].a, lg->arch.idt[num].b))
258 return 0; 258 return 0;
259 set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b, has_err(num)); 259 set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b,
260 has_err(num));
260 return 1; 261 return 1;
261} 262}
262 263
263/*H:250 Here's the hard part: returning to the Host every time a trap happens 264/*H:250 Here's the hard part: returning to the Host every time a trap happens
264 * and then calling deliver_trap() and re-entering the Guest is slow. 265 * and then calling deliver_trap() and re-entering the Guest is slow.
265 * Particularly because Guest userspace system calls are traps (trap 128). 266 * Particularly because Guest userspace system calls are traps (usually trap
267 * 128).
266 * 268 *
267 * So we'd like to set up the IDT to tell the CPU to deliver traps directly 269 * So we'd like to set up the IDT to tell the CPU to deliver traps directly
268 * into the Guest. This is possible, but the complexities cause the size of 270 * into the Guest. This is possible, but the complexities cause the size of
269 * this file to double! However, 150 lines of code is worth writing for taking 271 * this file to double! However, 150 lines of code is worth writing for taking
270 * system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all 272 * system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all
271 * the other hypervisors would tease it. 273 * the other hypervisors would beat it up at lunchtime.
272 * 274 *
273 * This routine indicates if a particular trap number could be delivered 275 * This routine indicates if a particular trap number could be delivered
274 * directly. */ 276 * directly. */
@@ -331,7 +333,7 @@ void pin_stack_pages(struct lguest *lg)
331 * change stacks on each context switch. */ 333 * change stacks on each context switch. */
332void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages) 334void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages)
333{ 335{
334 /* You are not allowd have a stack segment with privilege level 0: bad 336 /* You are not allowed have a stack segment with privilege level 0: bad
335 * Guest! */ 337 * Guest! */
336 if ((seg & 0x3) != GUEST_PL) 338 if ((seg & 0x3) != GUEST_PL)
337 kill_guest(lg, "bad stack segment %i", seg); 339 kill_guest(lg, "bad stack segment %i", seg);
@@ -350,7 +352,7 @@ void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages)
350 * part of the Host: page table handling. */ 352 * part of the Host: page table handling. */
351 353
352/*H:235 This is the routine which actually checks the Guest's IDT entry and 354/*H:235 This is the routine which actually checks the Guest's IDT entry and
353 * transfers it into our entry in "struct lguest": */ 355 * transfers it into the entry in "struct lguest": */
354static void set_trap(struct lguest *lg, struct desc_struct *trap, 356static void set_trap(struct lguest *lg, struct desc_struct *trap,
355 unsigned int num, u32 lo, u32 hi) 357 unsigned int num, u32 lo, u32 hi)
356{ 358{
@@ -456,6 +458,18 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
456 } 458 }
457} 459}
458 460
461/*H:200
462 * The Guest Clock.
463 *
464 * There are two sources of virtual interrupts. We saw one in lguest_user.c:
465 * the Launcher sending interrupts for virtual devices. The other is the Guest
466 * timer interrupt.
467 *
468 * The Guest uses the LHCALL_SET_CLOCKEVENT hypercall to tell us how long to
469 * the next timer interrupt (in nanoseconds). We use the high-resolution timer
470 * infrastructure to set a callback at that time.
471 *
472 * 0 means "turn off the clock". */
459void guest_set_clockevent(struct lguest *lg, unsigned long delta) 473void guest_set_clockevent(struct lguest *lg, unsigned long delta)
460{ 474{
461 ktime_t expires; 475 ktime_t expires;
@@ -466,20 +480,27 @@ void guest_set_clockevent(struct lguest *lg, unsigned long delta)
466 return; 480 return;
467 } 481 }
468 482
483 /* We use wallclock time here, so the Guest might not be running for
484 * all the time between now and the timer interrupt it asked for. This
485 * is almost always the right thing to do. */
469 expires = ktime_add_ns(ktime_get_real(), delta); 486 expires = ktime_add_ns(ktime_get_real(), delta);
470 hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS); 487 hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS);
471} 488}
472 489
490/* This is the function called when the Guest's timer expires. */
473static enum hrtimer_restart clockdev_fn(struct hrtimer *timer) 491static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
474{ 492{
475 struct lguest *lg = container_of(timer, struct lguest, hrt); 493 struct lguest *lg = container_of(timer, struct lguest, hrt);
476 494
495 /* Remember the first interrupt is the timer interrupt. */
477 set_bit(0, lg->irqs_pending); 496 set_bit(0, lg->irqs_pending);
497 /* If the Guest is actually stopped, we need to wake it up. */
478 if (lg->halted) 498 if (lg->halted)
479 wake_up_process(lg->tsk); 499 wake_up_process(lg->tsk);
480 return HRTIMER_NORESTART; 500 return HRTIMER_NORESTART;
481} 501}
482 502
503/* This sets up the timer for this Guest. */
483void init_clockdev(struct lguest *lg) 504void init_clockdev(struct lguest *lg)
484{ 505{
485 hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); 506 hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);