aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/interrupts_and_traps.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-07-26 13:41:04 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-26 14:35:17 -0400
commitbff672e630a015d5b54c8bfb16160b7edc39a57c (patch)
tree3af06baacb76809234a3e71033d14b7ed769dbd8 /drivers/lguest/interrupts_and_traps.c
parentdde797899ac17ebb812b7566044124d785e98dc7 (diff)
lguest: documentation V: Host
Documentation: The Host Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/lguest/interrupts_and_traps.c')
-rw-r--r--drivers/lguest/interrupts_and_traps.c176
1 files changed, 157 insertions, 19 deletions
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index b2647974e1a7..3d9830322646 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -14,100 +14,147 @@
14#include <linux/uaccess.h> 14#include <linux/uaccess.h>
15#include "lg.h" 15#include "lg.h"
16 16
17/* The address of the interrupt handler is split into two bits: */
17static unsigned long idt_address(u32 lo, u32 hi) 18static unsigned long idt_address(u32 lo, u32 hi)
18{ 19{
19 return (lo & 0x0000FFFF) | (hi & 0xFFFF0000); 20 return (lo & 0x0000FFFF) | (hi & 0xFFFF0000);
20} 21}
21 22
23/* The "type" of the interrupt handler is a 4 bit field: we only support a
24 * couple of types. */
22static int idt_type(u32 lo, u32 hi) 25static int idt_type(u32 lo, u32 hi)
23{ 26{
24 return (hi >> 8) & 0xF; 27 return (hi >> 8) & 0xF;
25} 28}
26 29
30/* An IDT entry can't be used unless the "present" bit is set. */
27static int idt_present(u32 lo, u32 hi) 31static int idt_present(u32 lo, u32 hi)
28{ 32{
29 return (hi & 0x8000); 33 return (hi & 0x8000);
30} 34}
31 35
36/* We need a helper to "push" a value onto the Guest's stack, since that's a
37 * big part of what delivering an interrupt does. */
32static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val) 38static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val)
33{ 39{
40 /* Stack grows upwards: move stack then write value. */
34 *gstack -= 4; 41 *gstack -= 4;
35 lgwrite_u32(lg, *gstack, val); 42 lgwrite_u32(lg, *gstack, val);
36} 43}
37 44
45/*H:210 The set_guest_interrupt() routine actually delivers the interrupt or
46 * trap. The mechanics of delivering traps and interrupts to the Guest are the
47 * same, except some traps have an "error code" which gets pushed onto the
48 * stack as well: the caller tells us if this is one.
49 *
50 * "lo" and "hi" are the two parts of the Interrupt Descriptor Table for this
51 * interrupt or trap. It's split into two parts for traditional reasons: gcc
52 * on i386 used to be frightened by 64 bit numbers.
53 *
54 * We set up the stack just like the CPU does for a real interrupt, so it's
55 * identical for the Guest (and the standard "iret" instruction will undo
56 * it). */
38static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err) 57static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
39{ 58{
40 unsigned long gstack; 59 unsigned long gstack;
41 u32 eflags, ss, irq_enable; 60 u32 eflags, ss, irq_enable;
42 61
43 /* If they want a ring change, we use new stack and push old ss/esp */ 62 /* There are two cases for interrupts: one where the Guest is already
63 * in the kernel, and a more complex one where the Guest is in
64 * userspace. We check the privilege level to find out. */
44 if ((lg->regs->ss&0x3) != GUEST_PL) { 65 if ((lg->regs->ss&0x3) != GUEST_PL) {
66 /* The Guest told us their kernel stack with the SET_STACK
67 * hypercall: both the virtual address and the segment */
45 gstack = guest_pa(lg, lg->esp1); 68 gstack = guest_pa(lg, lg->esp1);
46 ss = lg->ss1; 69 ss = lg->ss1;
70 /* We push the old stack segment and pointer onto the new
71 * stack: when the Guest does an "iret" back from the interrupt
72 * handler the CPU will notice they're dropping privilege
73 * levels and expect these here. */
47 push_guest_stack(lg, &gstack, lg->regs->ss); 74 push_guest_stack(lg, &gstack, lg->regs->ss);
48 push_guest_stack(lg, &gstack, lg->regs->esp); 75 push_guest_stack(lg, &gstack, lg->regs->esp);
49 } else { 76 } else {
77 /* We're staying on the same Guest (kernel) stack. */
50 gstack = guest_pa(lg, lg->regs->esp); 78 gstack = guest_pa(lg, lg->regs->esp);
51 ss = lg->regs->ss; 79 ss = lg->regs->ss;
52 } 80 }
53 81
54 /* We use IF bit in eflags to indicate whether irqs were enabled 82 /* Remember that we never let the Guest actually disable interrupts, so
55 (it's always 1, since irqs are enabled when guest is running). */ 83 * the "Interrupt Flag" bit is always set. We copy that bit from the
84 * Guest's "irq_enabled" field into the eflags word: the Guest copies
85 * it back in "lguest_iret". */
56 eflags = lg->regs->eflags; 86 eflags = lg->regs->eflags;
57 if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0 87 if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0
58 && !(irq_enable & X86_EFLAGS_IF)) 88 && !(irq_enable & X86_EFLAGS_IF))
59 eflags &= ~X86_EFLAGS_IF; 89 eflags &= ~X86_EFLAGS_IF;
60 90
91 /* An interrupt is expected to push three things on the stack: the old
92 * "eflags" word, the old code segment, and the old instruction
93 * pointer. */
61 push_guest_stack(lg, &gstack, eflags); 94 push_guest_stack(lg, &gstack, eflags);
62 push_guest_stack(lg, &gstack, lg->regs->cs); 95 push_guest_stack(lg, &gstack, lg->regs->cs);
63 push_guest_stack(lg, &gstack, lg->regs->eip); 96 push_guest_stack(lg, &gstack, lg->regs->eip);
64 97
98 /* For the six traps which supply an error code, we push that, too. */
65 if (has_err) 99 if (has_err)
66 push_guest_stack(lg, &gstack, lg->regs->errcode); 100 push_guest_stack(lg, &gstack, lg->regs->errcode);
67 101
68 /* Change the real stack so switcher returns to trap handler */ 102 /* Now we've pushed all the old state, we change the stack, the code
103 * segment and the address to execute. */
69 lg->regs->ss = ss; 104 lg->regs->ss = ss;
70 lg->regs->esp = gstack + lg->page_offset; 105 lg->regs->esp = gstack + lg->page_offset;
71 lg->regs->cs = (__KERNEL_CS|GUEST_PL); 106 lg->regs->cs = (__KERNEL_CS|GUEST_PL);
72 lg->regs->eip = idt_address(lo, hi); 107 lg->regs->eip = idt_address(lo, hi);
73 108
74 /* Disable interrupts for an interrupt gate. */ 109 /* There are two kinds of interrupt handlers: 0xE is an "interrupt
110 * gate" which expects interrupts to be disabled on entry. */
75 if (idt_type(lo, hi) == 0xE) 111 if (idt_type(lo, hi) == 0xE)
76 if (put_user(0, &lg->lguest_data->irq_enabled)) 112 if (put_user(0, &lg->lguest_data->irq_enabled))
77 kill_guest(lg, "Disabling interrupts"); 113 kill_guest(lg, "Disabling interrupts");
78} 114}
79 115
116/*H:200
117 * Virtual Interrupts.
118 *
119 * maybe_do_interrupt() gets called before every entry to the Guest, to see if
120 * we should divert the Guest to running an interrupt handler. */
80void maybe_do_interrupt(struct lguest *lg) 121void maybe_do_interrupt(struct lguest *lg)
81{ 122{
82 unsigned int irq; 123 unsigned int irq;
83 DECLARE_BITMAP(blk, LGUEST_IRQS); 124 DECLARE_BITMAP(blk, LGUEST_IRQS);
84 struct desc_struct *idt; 125 struct desc_struct *idt;
85 126
127 /* If the Guest hasn't even initialized yet, we can do nothing. */
86 if (!lg->lguest_data) 128 if (!lg->lguest_data)
87 return; 129 return;
88 130
89 /* Mask out any interrupts they have blocked. */ 131 /* Take our "irqs_pending" array and remove any interrupts the Guest
132 * wants blocked: the result ends up in "blk". */
90 if (copy_from_user(&blk, lg->lguest_data->blocked_interrupts, 133 if (copy_from_user(&blk, lg->lguest_data->blocked_interrupts,
91 sizeof(blk))) 134 sizeof(blk)))
92 return; 135 return;
93 136
94 bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS); 137 bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS);
95 138
139 /* Find the first interrupt. */
96 irq = find_first_bit(blk, LGUEST_IRQS); 140 irq = find_first_bit(blk, LGUEST_IRQS);
141 /* None? Nothing to do */
97 if (irq >= LGUEST_IRQS) 142 if (irq >= LGUEST_IRQS)
98 return; 143 return;
99 144
145 /* They may be in the middle of an iret, where they asked us never to
146 * deliver interrupts. */
100 if (lg->regs->eip >= lg->noirq_start && lg->regs->eip < lg->noirq_end) 147 if (lg->regs->eip >= lg->noirq_start && lg->regs->eip < lg->noirq_end)
101 return; 148 return;
102 149
103 /* If they're halted, we re-enable interrupts. */ 150 /* If they're halted, interrupts restart them. */
104 if (lg->halted) { 151 if (lg->halted) {
105 /* Re-enable interrupts. */ 152 /* Re-enable interrupts. */
106 if (put_user(X86_EFLAGS_IF, &lg->lguest_data->irq_enabled)) 153 if (put_user(X86_EFLAGS_IF, &lg->lguest_data->irq_enabled))
107 kill_guest(lg, "Re-enabling interrupts"); 154 kill_guest(lg, "Re-enabling interrupts");
108 lg->halted = 0; 155 lg->halted = 0;
109 } else { 156 } else {
110 /* Maybe they have interrupts disabled? */ 157 /* Otherwise we check if they have interrupts disabled. */
111 u32 irq_enabled; 158 u32 irq_enabled;
112 if (get_user(irq_enabled, &lg->lguest_data->irq_enabled)) 159 if (get_user(irq_enabled, &lg->lguest_data->irq_enabled))
113 irq_enabled = 0; 160 irq_enabled = 0;
@@ -115,112 +162,197 @@ void maybe_do_interrupt(struct lguest *lg)
115 return; 162 return;
116 } 163 }
117 164
165 /* Look at the IDT entry the Guest gave us for this interrupt. The
166 * first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip
167 * over them. */
118 idt = &lg->idt[FIRST_EXTERNAL_VECTOR+irq]; 168 idt = &lg->idt[FIRST_EXTERNAL_VECTOR+irq];
169 /* If they don't have a handler (yet?), we just ignore it */
119 if (idt_present(idt->a, idt->b)) { 170 if (idt_present(idt->a, idt->b)) {
171 /* OK, mark it no longer pending and deliver it. */
120 clear_bit(irq, lg->irqs_pending); 172 clear_bit(irq, lg->irqs_pending);
173 /* set_guest_interrupt() takes the interrupt descriptor and a
174 * flag to say whether this interrupt pushes an error code onto
175 * the stack as well: virtual interrupts never do. */
121 set_guest_interrupt(lg, idt->a, idt->b, 0); 176 set_guest_interrupt(lg, idt->a, idt->b, 0);
122 } 177 }
123} 178}
124 179
180/*H:220 Now we've got the routines to deliver interrupts, delivering traps
181 * like page fault is easy. The only trick is that Intel decided that some
182 * traps should have error codes: */
125static int has_err(unsigned int trap) 183static int has_err(unsigned int trap)
126{ 184{
127 return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17); 185 return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17);
128} 186}
129 187
188/* deliver_trap() returns true if it could deliver the trap. */
130int deliver_trap(struct lguest *lg, unsigned int num) 189int deliver_trap(struct lguest *lg, unsigned int num)
131{ 190{
132 u32 lo = lg->idt[num].a, hi = lg->idt[num].b; 191 u32 lo = lg->idt[num].a, hi = lg->idt[num].b;
133 192
193 /* Early on the Guest hasn't set the IDT entries (or maybe it put a
194 * bogus one in): if we fail here, the Guest will be killed. */
134 if (!idt_present(lo, hi)) 195 if (!idt_present(lo, hi))
135 return 0; 196 return 0;
136 set_guest_interrupt(lg, lo, hi, has_err(num)); 197 set_guest_interrupt(lg, lo, hi, has_err(num));
137 return 1; 198 return 1;
138} 199}
139 200
201/*H:250 Here's the hard part: returning to the Host every time a trap happens
202 * and then calling deliver_trap() and re-entering the Guest is slow.
203 * Particularly because Guest userspace system calls are traps (trap 128).
204 *
205 * So we'd like to set up the IDT to tell the CPU to deliver traps directly
206 * into the Guest. This is possible, but the complexities cause the size of
207 * this file to double! However, 150 lines of code is worth writing for taking
208 * system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all
209 * the other hypervisors would tease it.
210 *
211 * This routine determines if a trap can be delivered directly. */
140static int direct_trap(const struct lguest *lg, 212static int direct_trap(const struct lguest *lg,
141 const struct desc_struct *trap, 213 const struct desc_struct *trap,
142 unsigned int num) 214 unsigned int num)
143{ 215{
144 /* Hardware interrupts don't go to guest (except syscall). */ 216 /* Hardware interrupts don't go to the Guest at all (except system
217 * call). */
145 if (num >= FIRST_EXTERNAL_VECTOR && num != SYSCALL_VECTOR) 218 if (num >= FIRST_EXTERNAL_VECTOR && num != SYSCALL_VECTOR)
146 return 0; 219 return 0;
147 220
148 /* We intercept page fault (demand shadow paging & cr2 saving) 221 /* The Host needs to see page faults (for shadow paging and to save the
149 protection fault (in/out emulation) and device not 222 * fault address), general protection faults (in/out emulation) and
150 available (TS handling), and hypercall */ 223 * device not available (TS handling), and of course, the hypercall
224 * trap. */
151 if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY) 225 if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY)
152 return 0; 226 return 0;
153 227
154 /* Interrupt gates (0xE) or not present (0x0) can't go direct. */ 228 /* Only trap gates (type 15) can go direct to the Guest. Interrupt
229 * gates (type 14) disable interrupts as they are entered, which we
230 * never let the Guest do. Not present entries (type 0x0) also can't
231 * go direct, of course 8) */
155 return idt_type(trap->a, trap->b) == 0xF; 232 return idt_type(trap->a, trap->b) == 0xF;
156} 233}
157 234
235/*H:260 When we make traps go directly into the Guest, we need to make sure
236 * the kernel stack is valid (ie. mapped in the page tables). Otherwise, the
237 * CPU trying to deliver the trap will fault while trying to push the interrupt
238 * words on the stack: this is called a double fault, and it forces us to kill
239 * the Guest.
240 *
241 * Which is deeply unfair, because (literally!) it wasn't the Guests' fault. */
158void pin_stack_pages(struct lguest *lg) 242void pin_stack_pages(struct lguest *lg)
159{ 243{
160 unsigned int i; 244 unsigned int i;
161 245
246 /* Depending on the CONFIG_4KSTACKS option, the Guest can have one or
247 * two pages of stack space. */
162 for (i = 0; i < lg->stack_pages; i++) 248 for (i = 0; i < lg->stack_pages; i++)
249 /* The stack grows *upwards*, hence the subtraction */
163 pin_page(lg, lg->esp1 - i * PAGE_SIZE); 250 pin_page(lg, lg->esp1 - i * PAGE_SIZE);
164} 251}
165 252
253/* Direct traps also mean that we need to know whenever the Guest wants to use
254 * a different kernel stack, so we can change the IDT entries to use that
255 * stack. The IDT entries expect a virtual address, so unlike most addresses
256 * the Guest gives us, the "esp" (stack pointer) value here is virtual, not
257 * physical.
258 *
259 * In Linux each process has its own kernel stack, so this happens a lot: we
260 * change stacks on each context switch. */
166void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages) 261void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages)
167{ 262{
168 /* You cannot have a stack segment with priv level 0. */ 263 /* You are not allowd have a stack segment with privilege level 0: bad
264 * Guest! */
169 if ((seg & 0x3) != GUEST_PL) 265 if ((seg & 0x3) != GUEST_PL)
170 kill_guest(lg, "bad stack segment %i", seg); 266 kill_guest(lg, "bad stack segment %i", seg);
267 /* We only expect one or two stack pages. */
171 if (pages > 2) 268 if (pages > 2)
172 kill_guest(lg, "bad stack pages %u", pages); 269 kill_guest(lg, "bad stack pages %u", pages);
270 /* Save where the stack is, and how many pages */
173 lg->ss1 = seg; 271 lg->ss1 = seg;
174 lg->esp1 = esp; 272 lg->esp1 = esp;
175 lg->stack_pages = pages; 273 lg->stack_pages = pages;
274 /* Make sure the new stack pages are mapped */
176 pin_stack_pages(lg); 275 pin_stack_pages(lg);
177} 276}
178 277
179/* Set up trap in IDT. */ 278/* All this reference to mapping stacks leads us neatly into the other complex
279 * part of the Host: page table handling. */
280
281/*H:235 This is the routine which actually checks the Guest's IDT entry and
282 * transfers it into our entry in "struct lguest": */
180static void set_trap(struct lguest *lg, struct desc_struct *trap, 283static void set_trap(struct lguest *lg, struct desc_struct *trap,
181 unsigned int num, u32 lo, u32 hi) 284 unsigned int num, u32 lo, u32 hi)
182{ 285{
183 u8 type = idt_type(lo, hi); 286 u8 type = idt_type(lo, hi);
184 287
288 /* We zero-out a not-present entry */
185 if (!idt_present(lo, hi)) { 289 if (!idt_present(lo, hi)) {
186 trap->a = trap->b = 0; 290 trap->a = trap->b = 0;
187 return; 291 return;
188 } 292 }
189 293
294 /* We only support interrupt and trap gates. */
190 if (type != 0xE && type != 0xF) 295 if (type != 0xE && type != 0xF)
191 kill_guest(lg, "bad IDT type %i", type); 296 kill_guest(lg, "bad IDT type %i", type);
192 297
298 /* We only copy the handler address, present bit, privilege level and
299 * type. The privilege level controls where the trap can be triggered
300 * manually with an "int" instruction. This is usually GUEST_PL,
301 * except for system calls which userspace can use. */
193 trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF); 302 trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF);
194 trap->b = (hi&0xFFFFEF00); 303 trap->b = (hi&0xFFFFEF00);
195} 304}
196 305
306/*H:230 While we're here, dealing with delivering traps and interrupts to the
307 * Guest, we might as well complete the picture: how the Guest tells us where
308 * it wants them to go. This would be simple, except making traps fast
309 * requires some tricks.
310 *
311 * We saw the Guest setting Interrupt Descriptor Table (IDT) entries with the
312 * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here. */
197void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi) 313void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi)
198{ 314{
199 /* Guest never handles: NMI, doublefault, hypercall, spurious irq. */ 315 /* Guest never handles: NMI, doublefault, spurious interrupt or
316 * hypercall. We ignore when it tries to set them. */
200 if (num == 2 || num == 8 || num == 15 || num == LGUEST_TRAP_ENTRY) 317 if (num == 2 || num == 8 || num == 15 || num == LGUEST_TRAP_ENTRY)
201 return; 318 return;
202 319
320 /* Mark the IDT as changed: next time the Guest runs we'll know we have
321 * to copy this again. */
203 lg->changed |= CHANGED_IDT; 322 lg->changed |= CHANGED_IDT;
323
324 /* The IDT which we keep in "struct lguest" only contains 32 entries
325 * for the traps and LGUEST_IRQS (32) entries for interrupts. We
326 * ignore attempts to set handlers for higher interrupt numbers, except
327 * for the system call "interrupt" at 128: we have a special IDT entry
328 * for that. */
204 if (num < ARRAY_SIZE(lg->idt)) 329 if (num < ARRAY_SIZE(lg->idt))
205 set_trap(lg, &lg->idt[num], num, lo, hi); 330 set_trap(lg, &lg->idt[num], num, lo, hi);
206 else if (num == SYSCALL_VECTOR) 331 else if (num == SYSCALL_VECTOR)
207 set_trap(lg, &lg->syscall_idt, num, lo, hi); 332 set_trap(lg, &lg->syscall_idt, num, lo, hi);
208} 333}
209 334
335/* The default entry for each interrupt points into the Switcher routines which
336 * simply return to the Host. The run_guest() loop will then call
337 * deliver_trap() to bounce it back into the Guest. */
210static void default_idt_entry(struct desc_struct *idt, 338static void default_idt_entry(struct desc_struct *idt,
211 int trap, 339 int trap,
212 const unsigned long handler) 340 const unsigned long handler)
213{ 341{
342 /* A present interrupt gate. */
214 u32 flags = 0x8e00; 343 u32 flags = 0x8e00;
215 344
216 /* They can't "int" into any of them except hypercall. */ 345 /* Set the privilege level on the entry for the hypercall: this allows
346 * the Guest to use the "int" instruction to trigger it. */
217 if (trap == LGUEST_TRAP_ENTRY) 347 if (trap == LGUEST_TRAP_ENTRY)
218 flags |= (GUEST_PL << 13); 348 flags |= (GUEST_PL << 13);
219 349
350 /* Now pack it into the IDT entry in its weird format. */
220 idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF); 351 idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF);
221 idt->b = (handler&0xFFFF0000) | flags; 352 idt->b = (handler&0xFFFF0000) | flags;
222} 353}
223 354
355/* When the Guest first starts, we put default entries into the IDT. */
224void setup_default_idt_entries(struct lguest_ro_state *state, 356void setup_default_idt_entries(struct lguest_ro_state *state,
225 const unsigned long *def) 357 const unsigned long *def)
226{ 358{
@@ -230,19 +362,25 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
230 default_idt_entry(&state->guest_idt[i], i, def[i]); 362 default_idt_entry(&state->guest_idt[i], i, def[i]);
231} 363}
232 364
365/*H:240 We don't use the IDT entries in the "struct lguest" directly, instead
366 * we copy them into the IDT which we've set up for Guests on this CPU, just
367 * before we run the Guest. This routine does that copy. */
233void copy_traps(const struct lguest *lg, struct desc_struct *idt, 368void copy_traps(const struct lguest *lg, struct desc_struct *idt,
234 const unsigned long *def) 369 const unsigned long *def)
235{ 370{
236 unsigned int i; 371 unsigned int i;
237 372
238 /* All hardware interrupts are same whatever the guest: only the 373 /* We can simply copy the direct traps, otherwise we use the default
239 * traps might be different. */ 374 * ones in the Switcher: they will return to the Host. */
240 for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) { 375 for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) {
241 if (direct_trap(lg, &lg->idt[i], i)) 376 if (direct_trap(lg, &lg->idt[i], i))
242 idt[i] = lg->idt[i]; 377 idt[i] = lg->idt[i];
243 else 378 else
244 default_idt_entry(&idt[i], i, def[i]); 379 default_idt_entry(&idt[i], i, def[i]);
245 } 380 }
381
382 /* Don't forget the system call trap! The IDT entries for other
383 * interupts never change, so no need to copy them. */
246 i = SYSCALL_VECTOR; 384 i = SYSCALL_VECTOR;
247 if (direct_trap(lg, &lg->syscall_idt, i)) 385 if (direct_trap(lg, &lg->syscall_idt, i))
248 idt[i] = lg->syscall_idt; 386 idt[i] = lg->syscall_idt;