aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/interrupts_and_traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest/interrupts_and_traps.c')
-rw-r--r--drivers/lguest/interrupts_and_traps.c205
1 files changed, 185 insertions, 20 deletions
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index bee029bb2c7b..bd0091bf79ec 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -1,100 +1,160 @@
1/*P:800 Interrupts (traps) are complicated enough to earn their own file.
2 * There are three classes of interrupts:
3 *
4 * 1) Real hardware interrupts which occur while we're running the Guest,
5 * 2) Interrupts for virtual devices attached to the Guest, and
6 * 3) Traps and faults from the Guest.
7 *
8 * Real hardware interrupts must be delivered to the Host, not the Guest.
9 * Virtual interrupts must be delivered to the Guest, but we make them look
10 * just like real hardware would deliver them. Traps from the Guest can be set
11 * up to go directly back into the Guest, but sometimes the Host wants to see
12 * them first, so we also have a way of "reflecting" them into the Guest as if
13 * they had been delivered to it directly. :*/
1#include <linux/uaccess.h> 14#include <linux/uaccess.h>
2#include "lg.h" 15#include "lg.h"
3 16
17/* The address of the interrupt handler is split into two bits: */
4static unsigned long idt_address(u32 lo, u32 hi) 18static unsigned long idt_address(u32 lo, u32 hi)
5{ 19{
6 return (lo & 0x0000FFFF) | (hi & 0xFFFF0000); 20 return (lo & 0x0000FFFF) | (hi & 0xFFFF0000);
7} 21}
8 22
23/* The "type" of the interrupt handler is a 4 bit field: we only support a
24 * couple of types. */
9static int idt_type(u32 lo, u32 hi) 25static int idt_type(u32 lo, u32 hi)
10{ 26{
11 return (hi >> 8) & 0xF; 27 return (hi >> 8) & 0xF;
12} 28}
13 29
30/* An IDT entry can't be used unless the "present" bit is set. */
14static int idt_present(u32 lo, u32 hi) 31static int idt_present(u32 lo, u32 hi)
15{ 32{
16 return (hi & 0x8000); 33 return (hi & 0x8000);
17} 34}
18 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. */
19static 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)
20{ 39{
40 /* Stack grows upwards: move stack then write value. */
21 *gstack -= 4; 41 *gstack -= 4;
22 lgwrite_u32(lg, *gstack, val); 42 lgwrite_u32(lg, *gstack, val);
23} 43}
24 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). */
25static 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)
26{ 58{
27 unsigned long gstack; 59 unsigned long gstack;
28 u32 eflags, ss, irq_enable; 60 u32 eflags, ss, irq_enable;
29 61
30 /* 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. */
31 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 */
32 gstack = guest_pa(lg, lg->esp1); 68 gstack = guest_pa(lg, lg->esp1);
33 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. */
34 push_guest_stack(lg, &gstack, lg->regs->ss); 74 push_guest_stack(lg, &gstack, lg->regs->ss);
35 push_guest_stack(lg, &gstack, lg->regs->esp); 75 push_guest_stack(lg, &gstack, lg->regs->esp);
36 } else { 76 } else {
77 /* We're staying on the same Guest (kernel) stack. */
37 gstack = guest_pa(lg, lg->regs->esp); 78 gstack = guest_pa(lg, lg->regs->esp);
38 ss = lg->regs->ss; 79 ss = lg->regs->ss;
39 } 80 }
40 81
41 /* We use IF bit in eflags to indicate whether irqs were enabled 82 /* Remember that we never let the Guest actually disable interrupts, so
42 (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". */
43 eflags = lg->regs->eflags; 86 eflags = lg->regs->eflags;
44 if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0 87 if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0
45 && !(irq_enable & X86_EFLAGS_IF)) 88 && !(irq_enable & X86_EFLAGS_IF))
46 eflags &= ~X86_EFLAGS_IF; 89 eflags &= ~X86_EFLAGS_IF;
47 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. */
48 push_guest_stack(lg, &gstack, eflags); 94 push_guest_stack(lg, &gstack, eflags);
49 push_guest_stack(lg, &gstack, lg->regs->cs); 95 push_guest_stack(lg, &gstack, lg->regs->cs);
50 push_guest_stack(lg, &gstack, lg->regs->eip); 96 push_guest_stack(lg, &gstack, lg->regs->eip);
51 97
98 /* For the six traps which supply an error code, we push that, too. */
52 if (has_err) 99 if (has_err)
53 push_guest_stack(lg, &gstack, lg->regs->errcode); 100 push_guest_stack(lg, &gstack, lg->regs->errcode);
54 101
55 /* 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. */
56 lg->regs->ss = ss; 104 lg->regs->ss = ss;
57 lg->regs->esp = gstack + lg->page_offset; 105 lg->regs->esp = gstack + lg->page_offset;
58 lg->regs->cs = (__KERNEL_CS|GUEST_PL); 106 lg->regs->cs = (__KERNEL_CS|GUEST_PL);
59 lg->regs->eip = idt_address(lo, hi); 107 lg->regs->eip = idt_address(lo, hi);
60 108
61 /* 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. */
62 if (idt_type(lo, hi) == 0xE) 111 if (idt_type(lo, hi) == 0xE)
63 if (put_user(0, &lg->lguest_data->irq_enabled)) 112 if (put_user(0, &lg->lguest_data->irq_enabled))
64 kill_guest(lg, "Disabling interrupts"); 113 kill_guest(lg, "Disabling interrupts");
65} 114}
66 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. */
67void maybe_do_interrupt(struct lguest *lg) 121void maybe_do_interrupt(struct lguest *lg)
68{ 122{
69 unsigned int irq; 123 unsigned int irq;
70 DECLARE_BITMAP(blk, LGUEST_IRQS); 124 DECLARE_BITMAP(blk, LGUEST_IRQS);
71 struct desc_struct *idt; 125 struct desc_struct *idt;
72 126
127 /* If the Guest hasn't even initialized yet, we can do nothing. */
73 if (!lg->lguest_data) 128 if (!lg->lguest_data)
74 return; 129 return;
75 130
76 /* 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". */
77 if (copy_from_user(&blk, lg->lguest_data->blocked_interrupts, 133 if (copy_from_user(&blk, lg->lguest_data->blocked_interrupts,
78 sizeof(blk))) 134 sizeof(blk)))
79 return; 135 return;
80 136
81 bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS); 137 bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS);
82 138
139 /* Find the first interrupt. */
83 irq = find_first_bit(blk, LGUEST_IRQS); 140 irq = find_first_bit(blk, LGUEST_IRQS);
141 /* None? Nothing to do */
84 if (irq >= LGUEST_IRQS) 142 if (irq >= LGUEST_IRQS)
85 return; 143 return;
86 144
145 /* They may be in the middle of an iret, where they asked us never to
146 * deliver interrupts. */
87 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)
88 return; 148 return;
89 149
90 /* If they're halted, we re-enable interrupts. */ 150 /* If they're halted, interrupts restart them. */
91 if (lg->halted) { 151 if (lg->halted) {
92 /* Re-enable interrupts. */ 152 /* Re-enable interrupts. */
93 if (put_user(X86_EFLAGS_IF, &lg->lguest_data->irq_enabled)) 153 if (put_user(X86_EFLAGS_IF, &lg->lguest_data->irq_enabled))
94 kill_guest(lg, "Re-enabling interrupts"); 154 kill_guest(lg, "Re-enabling interrupts");
95 lg->halted = 0; 155 lg->halted = 0;
96 } else { 156 } else {
97 /* Maybe they have interrupts disabled? */ 157 /* Otherwise we check if they have interrupts disabled. */
98 u32 irq_enabled; 158 u32 irq_enabled;
99 if (get_user(irq_enabled, &lg->lguest_data->irq_enabled)) 159 if (get_user(irq_enabled, &lg->lguest_data->irq_enabled))
100 irq_enabled = 0; 160 irq_enabled = 0;
@@ -102,112 +162,211 @@ void maybe_do_interrupt(struct lguest *lg)
102 return; 162 return;
103 } 163 }
104 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. */
105 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 */
106 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. */
107 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. */
108 set_guest_interrupt(lg, idt->a, idt->b, 0); 176 set_guest_interrupt(lg, idt->a, idt->b, 0);
109 } 177 }
110} 178}
111 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: */
112static int has_err(unsigned int trap) 183static int has_err(unsigned int trap)
113{ 184{
114 return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17); 185 return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17);
115} 186}
116 187
188/* deliver_trap() returns true if it could deliver the trap. */
117int deliver_trap(struct lguest *lg, unsigned int num) 189int deliver_trap(struct lguest *lg, unsigned int num)
118{ 190{
119 u32 lo = lg->idt[num].a, hi = lg->idt[num].b; 191 u32 lo = lg->idt[num].a, hi = lg->idt[num].b;
120 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. */
121 if (!idt_present(lo, hi)) 195 if (!idt_present(lo, hi))
122 return 0; 196 return 0;
123 set_guest_interrupt(lg, lo, hi, has_err(num)); 197 set_guest_interrupt(lg, lo, hi, has_err(num));
124 return 1; 198 return 1;
125} 199}
126 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. */
127static int direct_trap(const struct lguest *lg, 212static int direct_trap(const struct lguest *lg,
128 const struct desc_struct *trap, 213 const struct desc_struct *trap,
129 unsigned int num) 214 unsigned int num)
130{ 215{
131 /* Hardware interrupts don't go to guest (except syscall). */ 216 /* Hardware interrupts don't go to the Guest at all (except system
217 * call). */
132 if (num >= FIRST_EXTERNAL_VECTOR && num != SYSCALL_VECTOR) 218 if (num >= FIRST_EXTERNAL_VECTOR && num != SYSCALL_VECTOR)
133 return 0; 219 return 0;
134 220
135 /* We intercept page fault (demand shadow paging & cr2 saving) 221 /* The Host needs to see page faults (for shadow paging and to save the
136 protection fault (in/out emulation) and device not 222 * fault address), general protection faults (in/out emulation) and
137 available (TS handling), and hypercall */ 223 * device not available (TS handling), and of course, the hypercall
224 * trap. */
138 if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY) 225 if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY)
139 return 0; 226 return 0;
140 227
141 /* 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) */
142 return idt_type(trap->a, trap->b) == 0xF; 232 return idt_type(trap->a, trap->b) == 0xF;
143} 233}
144 234/*:*/
235
236/*M:005 The Guest has the ability to turn its interrupt gates into trap gates,
237 * if it is careful. The Host will let trap gates can go directly to the
238 * Guest, but the Guest needs the interrupts atomically disabled for an
239 * interrupt gate. It can do this by pointing the trap gate at instructions
240 * within noirq_start and noirq_end, where it can safely disable interrupts. */
241
242/*M:006 The Guests do not use the sysenter (fast system call) instruction,
243 * because it's hardcoded to enter privilege level 0 and so can't go direct.
244 * It's about twice as fast as the older "int 0x80" system call, so it might
245 * still be worthwhile to handle it in the Switcher and lcall down to the
246 * Guest. The sysenter semantics are hairy tho: search for that keyword in
247 * entry.S :*/
248
249/*H:260 When we make traps go directly into the Guest, we need to make sure
250 * the kernel stack is valid (ie. mapped in the page tables). Otherwise, the
251 * CPU trying to deliver the trap will fault while trying to push the interrupt
252 * words on the stack: this is called a double fault, and it forces us to kill
253 * the Guest.
254 *
255 * Which is deeply unfair, because (literally!) it wasn't the Guests' fault. */
145void pin_stack_pages(struct lguest *lg) 256void pin_stack_pages(struct lguest *lg)
146{ 257{
147 unsigned int i; 258 unsigned int i;
148 259
260 /* Depending on the CONFIG_4KSTACKS option, the Guest can have one or
261 * two pages of stack space. */
149 for (i = 0; i < lg->stack_pages; i++) 262 for (i = 0; i < lg->stack_pages; i++)
263 /* The stack grows *upwards*, hence the subtraction */
150 pin_page(lg, lg->esp1 - i * PAGE_SIZE); 264 pin_page(lg, lg->esp1 - i * PAGE_SIZE);
151} 265}
152 266
267/* Direct traps also mean that we need to know whenever the Guest wants to use
268 * a different kernel stack, so we can change the IDT entries to use that
269 * stack. The IDT entries expect a virtual address, so unlike most addresses
270 * the Guest gives us, the "esp" (stack pointer) value here is virtual, not
271 * physical.
272 *
273 * In Linux each process has its own kernel stack, so this happens a lot: we
274 * change stacks on each context switch. */
153void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages) 275void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages)
154{ 276{
155 /* You cannot have a stack segment with priv level 0. */ 277 /* You are not allowd have a stack segment with privilege level 0: bad
278 * Guest! */
156 if ((seg & 0x3) != GUEST_PL) 279 if ((seg & 0x3) != GUEST_PL)
157 kill_guest(lg, "bad stack segment %i", seg); 280 kill_guest(lg, "bad stack segment %i", seg);
281 /* We only expect one or two stack pages. */
158 if (pages > 2) 282 if (pages > 2)
159 kill_guest(lg, "bad stack pages %u", pages); 283 kill_guest(lg, "bad stack pages %u", pages);
284 /* Save where the stack is, and how many pages */
160 lg->ss1 = seg; 285 lg->ss1 = seg;
161 lg->esp1 = esp; 286 lg->esp1 = esp;
162 lg->stack_pages = pages; 287 lg->stack_pages = pages;
288 /* Make sure the new stack pages are mapped */
163 pin_stack_pages(lg); 289 pin_stack_pages(lg);
164} 290}
165 291
166/* Set up trap in IDT. */ 292/* All this reference to mapping stacks leads us neatly into the other complex
293 * part of the Host: page table handling. */
294
295/*H:235 This is the routine which actually checks the Guest's IDT entry and
296 * transfers it into our entry in "struct lguest": */
167static void set_trap(struct lguest *lg, struct desc_struct *trap, 297static void set_trap(struct lguest *lg, struct desc_struct *trap,
168 unsigned int num, u32 lo, u32 hi) 298 unsigned int num, u32 lo, u32 hi)
169{ 299{
170 u8 type = idt_type(lo, hi); 300 u8 type = idt_type(lo, hi);
171 301
302 /* We zero-out a not-present entry */
172 if (!idt_present(lo, hi)) { 303 if (!idt_present(lo, hi)) {
173 trap->a = trap->b = 0; 304 trap->a = trap->b = 0;
174 return; 305 return;
175 } 306 }
176 307
308 /* We only support interrupt and trap gates. */
177 if (type != 0xE && type != 0xF) 309 if (type != 0xE && type != 0xF)
178 kill_guest(lg, "bad IDT type %i", type); 310 kill_guest(lg, "bad IDT type %i", type);
179 311
312 /* We only copy the handler address, present bit, privilege level and
313 * type. The privilege level controls where the trap can be triggered
314 * manually with an "int" instruction. This is usually GUEST_PL,
315 * except for system calls which userspace can use. */
180 trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF); 316 trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF);
181 trap->b = (hi&0xFFFFEF00); 317 trap->b = (hi&0xFFFFEF00);
182} 318}
183 319
320/*H:230 While we're here, dealing with delivering traps and interrupts to the
321 * Guest, we might as well complete the picture: how the Guest tells us where
322 * it wants them to go. This would be simple, except making traps fast
323 * requires some tricks.
324 *
325 * We saw the Guest setting Interrupt Descriptor Table (IDT) entries with the
326 * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here. */
184void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi) 327void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi)
185{ 328{
186 /* Guest never handles: NMI, doublefault, hypercall, spurious irq. */ 329 /* Guest never handles: NMI, doublefault, spurious interrupt or
330 * hypercall. We ignore when it tries to set them. */
187 if (num == 2 || num == 8 || num == 15 || num == LGUEST_TRAP_ENTRY) 331 if (num == 2 || num == 8 || num == 15 || num == LGUEST_TRAP_ENTRY)
188 return; 332 return;
189 333
334 /* Mark the IDT as changed: next time the Guest runs we'll know we have
335 * to copy this again. */
190 lg->changed |= CHANGED_IDT; 336 lg->changed |= CHANGED_IDT;
337
338 /* The IDT which we keep in "struct lguest" only contains 32 entries
339 * for the traps and LGUEST_IRQS (32) entries for interrupts. We
340 * ignore attempts to set handlers for higher interrupt numbers, except
341 * for the system call "interrupt" at 128: we have a special IDT entry
342 * for that. */
191 if (num < ARRAY_SIZE(lg->idt)) 343 if (num < ARRAY_SIZE(lg->idt))
192 set_trap(lg, &lg->idt[num], num, lo, hi); 344 set_trap(lg, &lg->idt[num], num, lo, hi);
193 else if (num == SYSCALL_VECTOR) 345 else if (num == SYSCALL_VECTOR)
194 set_trap(lg, &lg->syscall_idt, num, lo, hi); 346 set_trap(lg, &lg->syscall_idt, num, lo, hi);
195} 347}
196 348
349/* The default entry for each interrupt points into the Switcher routines which
350 * simply return to the Host. The run_guest() loop will then call
351 * deliver_trap() to bounce it back into the Guest. */
197static void default_idt_entry(struct desc_struct *idt, 352static void default_idt_entry(struct desc_struct *idt,
198 int trap, 353 int trap,
199 const unsigned long handler) 354 const unsigned long handler)
200{ 355{
356 /* A present interrupt gate. */
201 u32 flags = 0x8e00; 357 u32 flags = 0x8e00;
202 358
203 /* They can't "int" into any of them except hypercall. */ 359 /* Set the privilege level on the entry for the hypercall: this allows
360 * the Guest to use the "int" instruction to trigger it. */
204 if (trap == LGUEST_TRAP_ENTRY) 361 if (trap == LGUEST_TRAP_ENTRY)
205 flags |= (GUEST_PL << 13); 362 flags |= (GUEST_PL << 13);
206 363
364 /* Now pack it into the IDT entry in its weird format. */
207 idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF); 365 idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF);
208 idt->b = (handler&0xFFFF0000) | flags; 366 idt->b = (handler&0xFFFF0000) | flags;
209} 367}
210 368
369/* When the Guest first starts, we put default entries into the IDT. */
211void setup_default_idt_entries(struct lguest_ro_state *state, 370void setup_default_idt_entries(struct lguest_ro_state *state,
212 const unsigned long *def) 371 const unsigned long *def)
213{ 372{
@@ -217,19 +376,25 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
217 default_idt_entry(&state->guest_idt[i], i, def[i]); 376 default_idt_entry(&state->guest_idt[i], i, def[i]);
218} 377}
219 378
379/*H:240 We don't use the IDT entries in the "struct lguest" directly, instead
380 * we copy them into the IDT which we've set up for Guests on this CPU, just
381 * before we run the Guest. This routine does that copy. */
220void copy_traps(const struct lguest *lg, struct desc_struct *idt, 382void copy_traps(const struct lguest *lg, struct desc_struct *idt,
221 const unsigned long *def) 383 const unsigned long *def)
222{ 384{
223 unsigned int i; 385 unsigned int i;
224 386
225 /* All hardware interrupts are same whatever the guest: only the 387 /* We can simply copy the direct traps, otherwise we use the default
226 * traps might be different. */ 388 * ones in the Switcher: they will return to the Host. */
227 for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) { 389 for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) {
228 if (direct_trap(lg, &lg->idt[i], i)) 390 if (direct_trap(lg, &lg->idt[i], i))
229 idt[i] = lg->idt[i]; 391 idt[i] = lg->idt[i];
230 else 392 else
231 default_idt_entry(&idt[i], i, def[i]); 393 default_idt_entry(&idt[i], i, def[i]);
232 } 394 }
395
396 /* Don't forget the system call trap! The IDT entries for other
397 * interupts never change, so no need to copy them. */
233 i = SYSCALL_VECTOR; 398 i = SYSCALL_VECTOR;
234 if (direct_trap(lg, &lg->syscall_idt, i)) 399 if (direct_trap(lg, &lg->syscall_idt, i))
235 idt[i] = lg->syscall_idt; 400 idt[i] = lg->syscall_idt;