diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-25 01:02:50 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-25 01:02:50 -0400 |
commit | e1e72965ec2c02db99b415cd06c17ea90767e3a4 (patch) | |
tree | 94e43aac35bdc33220e64f285b72b3b2b787fd57 /drivers/lguest | |
parent | 568a17ffce2eeceae0cd9fc37e97cbad12f70278 (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')
-rw-r--r-- | drivers/lguest/core.c | 5 | ||||
-rw-r--r-- | drivers/lguest/hypercalls.c | 11 | ||||
-rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 37 | ||||
-rw-r--r-- | drivers/lguest/lg.h | 4 | ||||
-rw-r--r-- | drivers/lguest/lguest_device.c | 11 | ||||
-rw-r--r-- | drivers/lguest/lguest_user.c | 23 | ||||
-rw-r--r-- | drivers/lguest/page_tables.c | 113 | ||||
-rw-r--r-- | drivers/lguest/segments.c | 48 | ||||
-rw-r--r-- | drivers/lguest/x86/core.c | 120 | ||||
-rw-r--r-- | drivers/lguest/x86/switcher_32.S | 71 |
10 files changed, 274 insertions, 169 deletions
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index 35d19ae58de7..cb4c67025d52 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c | |||
@@ -128,9 +128,12 @@ static void unmap_switcher(void) | |||
128 | __free_pages(switcher_page[i], 0); | 128 | __free_pages(switcher_page[i], 0); |
129 | } | 129 | } |
130 | 130 | ||
131 | /*L:305 | 131 | /*H:032 |
132 | * Dealing With Guest Memory. | 132 | * Dealing With Guest Memory. |
133 | * | 133 | * |
134 | * Before we go too much further into the Host, we need to grok the routines | ||
135 | * we use to deal with Guest memory. | ||
136 | * | ||
134 | * When the Guest gives us (what it thinks is) a physical address, we can use | 137 | * When the Guest gives us (what it thinks is) a physical address, we can use |
135 | * the normal copy_from_user() & copy_to_user() on the corresponding place in | 138 | * the normal copy_from_user() & copy_to_user() on the corresponding place in |
136 | * the memory region allocated by the Launcher. | 139 | * the memory region allocated by the Launcher. |
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 9d5184c7c14a..b478affe8f91 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c | |||
@@ -90,6 +90,7 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args) | |||
90 | lg->pending_notify = args->arg1; | 90 | lg->pending_notify = args->arg1; |
91 | break; | 91 | break; |
92 | default: | 92 | default: |
93 | /* It should be an architecture-specific hypercall. */ | ||
93 | if (lguest_arch_do_hcall(lg, args)) | 94 | if (lguest_arch_do_hcall(lg, args)) |
94 | kill_guest(lg, "Bad hypercall %li\n", args->arg0); | 95 | kill_guest(lg, "Bad hypercall %li\n", args->arg0); |
95 | } | 96 | } |
@@ -157,7 +158,6 @@ static void do_async_hcalls(struct lguest *lg) | |||
157 | * Guest makes a hypercall, we end up here to set things up: */ | 158 | * Guest makes a hypercall, we end up here to set things up: */ |
158 | static void initialize(struct lguest *lg) | 159 | static void initialize(struct lguest *lg) |
159 | { | 160 | { |
160 | |||
161 | /* You can't do anything until you're initialized. The Guest knows the | 161 | /* You can't do anything until you're initialized. The Guest knows the |
162 | * rules, so we're unforgiving here. */ | 162 | * rules, so we're unforgiving here. */ |
163 | if (lg->hcall->arg0 != LHCALL_LGUEST_INIT) { | 163 | if (lg->hcall->arg0 != LHCALL_LGUEST_INIT) { |
@@ -174,7 +174,8 @@ static void initialize(struct lguest *lg) | |||
174 | || get_user(lg->noirq_end, &lg->lguest_data->noirq_end)) | 174 | || get_user(lg->noirq_end, &lg->lguest_data->noirq_end)) |
175 | kill_guest(lg, "bad guest page %p", lg->lguest_data); | 175 | kill_guest(lg, "bad guest page %p", lg->lguest_data); |
176 | 176 | ||
177 | /* We write the current time into the Guest's data page once now. */ | 177 | /* We write the current time into the Guest's data page once so it can |
178 | * set its clock. */ | ||
178 | write_timestamp(lg); | 179 | write_timestamp(lg); |
179 | 180 | ||
180 | /* page_tables.c will also do some setup. */ | 181 | /* page_tables.c will also do some setup. */ |
@@ -182,8 +183,8 @@ static void initialize(struct lguest *lg) | |||
182 | 183 | ||
183 | /* This is the one case where the above accesses might have been the | 184 | /* This is the one case where the above accesses might have been the |
184 | * first write to a Guest page. This may have caused a copy-on-write | 185 | * first write to a Guest page. This may have caused a copy-on-write |
185 | * fault, but the Guest might be referring to the old (read-only) | 186 | * fault, but the old page might be (read-only) in the Guest |
186 | * page. */ | 187 | * pagetable. */ |
187 | guest_pagetable_clear_all(lg); | 188 | guest_pagetable_clear_all(lg); |
188 | } | 189 | } |
189 | 190 | ||
@@ -220,7 +221,7 @@ void do_hypercalls(struct lguest *lg) | |||
220 | * Normally it doesn't matter: the Guest will run again and | 221 | * Normally it doesn't matter: the Guest will run again and |
221 | * update the trap number before we come back here. | 222 | * update the trap number before we come back here. |
222 | * | 223 | * |
223 | * However, if we are signalled or the Guest sends DMA to the | 224 | * However, if we are signalled or the Guest sends I/O to the |
224 | * Launcher, the run_guest() loop will exit without running the | 225 | * Launcher, the run_guest() loop will exit without running the |
225 | * Guest. When it comes back it would try to re-run the | 226 | * Guest. When it comes back it would try to re-run the |
226 | * hypercall. */ | 227 | * hypercall. */ |
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 82966982cb38..2b66f79c208b 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. */ |
332 | void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages) | 334 | void 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": */ |
354 | static void set_trap(struct lguest *lg, struct desc_struct *trap, | 356 | static 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". */ | ||
459 | void guest_set_clockevent(struct lguest *lg, unsigned long delta) | 473 | void 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. */ | ||
473 | static enum hrtimer_restart clockdev_fn(struct hrtimer *timer) | 491 | static 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. */ | ||
483 | void init_clockdev(struct lguest *lg) | 504 | void 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); |
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index 0c74ac42cf01..86924891b5eb 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h | |||
@@ -100,7 +100,7 @@ int lguest_address_ok(const struct lguest *lg, | |||
100 | void __lgread(struct lguest *, void *, unsigned long, unsigned); | 100 | void __lgread(struct lguest *, void *, unsigned long, unsigned); |
101 | void __lgwrite(struct lguest *, unsigned long, const void *, unsigned); | 101 | void __lgwrite(struct lguest *, unsigned long, const void *, unsigned); |
102 | 102 | ||
103 | /*L:306 Using memory-copy operations like that is usually inconvient, so we | 103 | /*H:035 Using memory-copy operations like that is usually inconvient, so we |
104 | * have the following helper macros which read and write a specific type (often | 104 | * have the following helper macros which read and write a specific type (often |
105 | * an unsigned long). | 105 | * an unsigned long). |
106 | * | 106 | * |
@@ -188,7 +188,7 @@ void write_timestamp(struct lguest *lg); | |||
188 | * Let's step aside for the moment, to study one important routine that's used | 188 | * Let's step aside for the moment, to study one important routine that's used |
189 | * widely in the Host code. | 189 | * widely in the Host code. |
190 | * | 190 | * |
191 | * There are many cases where the Guest does something invalid, like pass crap | 191 | * There are many cases where the Guest can do something invalid, like pass crap |
192 | * to a hypercall. Since only the Guest kernel can make hypercalls, it's quite | 192 | * to a hypercall. Since only the Guest kernel can make hypercalls, it's quite |
193 | * acceptable to simply terminate the Guest and give the Launcher a nicely | 193 | * acceptable to simply terminate the Guest and give the Launcher a nicely |
194 | * formatted reason. It's also simpler for the Guest itself, which doesn't | 194 | * formatted reason. It's also simpler for the Guest itself, which doesn't |
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 71c64837b437..8904f72f97c6 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
@@ -53,7 +53,8 @@ struct lguest_device { | |||
53 | * Device configurations | 53 | * Device configurations |
54 | * | 54 | * |
55 | * The configuration information for a device consists of a series of fields. | 55 | * The configuration information for a device consists of a series of fields. |
56 | * The device will look for these fields during setup. | 56 | * We don't really care what they are: the Launcher set them up, and the driver |
57 | * will look at them during setup. | ||
57 | * | 58 | * |
58 | * For us these fields come immediately after that device's descriptor in the | 59 | * For us these fields come immediately after that device's descriptor in the |
59 | * lguest_devices page. | 60 | * lguest_devices page. |
@@ -122,8 +123,8 @@ static void lg_set_status(struct virtio_device *vdev, u8 status) | |||
122 | * The other piece of infrastructure virtio needs is a "virtqueue": a way of | 123 | * The other piece of infrastructure virtio needs is a "virtqueue": a way of |
123 | * the Guest device registering buffers for the other side to read from or | 124 | * the Guest device registering buffers for the other side to read from or |
124 | * write into (ie. send and receive buffers). Each device can have multiple | 125 | * write into (ie. send and receive buffers). Each device can have multiple |
125 | * virtqueues: for example the console has one queue for sending and one for | 126 | * virtqueues: for example the console driver uses one queue for sending and |
126 | * receiving. | 127 | * another for receiving. |
127 | * | 128 | * |
128 | * Fortunately for us, a very fast shared-memory-plus-descriptors virtqueue | 129 | * Fortunately for us, a very fast shared-memory-plus-descriptors virtqueue |
129 | * already exists in virtio_ring.c. We just need to connect it up. | 130 | * already exists in virtio_ring.c. We just need to connect it up. |
@@ -158,7 +159,7 @@ static void lg_notify(struct virtqueue *vq) | |||
158 | * | 159 | * |
159 | * This is kind of an ugly duckling. It'd be nicer to have a standard | 160 | * This is kind of an ugly duckling. It'd be nicer to have a standard |
160 | * representation of a virtqueue in the configuration space, but it seems that | 161 | * representation of a virtqueue in the configuration space, but it seems that |
161 | * everyone wants to do it differently. The KVM guys want the Guest to | 162 | * everyone wants to do it differently. The KVM coders want the Guest to |
162 | * allocate its own pages and tell the Host where they are, but for lguest it's | 163 | * allocate its own pages and tell the Host where they are, but for lguest it's |
163 | * simpler for the Host to simply tell us where the pages are. | 164 | * simpler for the Host to simply tell us where the pages are. |
164 | * | 165 | * |
@@ -284,6 +285,8 @@ static void add_lguest_device(struct lguest_device_desc *d) | |||
284 | { | 285 | { |
285 | struct lguest_device *ldev; | 286 | struct lguest_device *ldev; |
286 | 287 | ||
288 | /* Start with zeroed memory; Linux's device layer seems to count on | ||
289 | * it. */ | ||
287 | ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); | 290 | ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); |
288 | if (!ldev) { | 291 | if (!ldev) { |
289 | printk(KERN_EMERG "Cannot allocate lguest dev %u\n", | 292 | printk(KERN_EMERG "Cannot allocate lguest dev %u\n", |
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index ee405b38383d..9d716fa42cad 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c | |||
@@ -8,20 +8,22 @@ | |||
8 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
9 | #include "lg.h" | 9 | #include "lg.h" |
10 | 10 | ||
11 | /*L:315 To force the Guest to stop running and return to the Launcher, the | 11 | /*L:055 When something happens, the Waker process needs a way to stop the |
12 | * Waker sets writes LHREQ_BREAK and the value "1" to /dev/lguest. The | 12 | * kernel running the Guest and return to the Launcher. So the Waker writes |
13 | * Launcher then writes LHREQ_BREAK and "0" to release the Waker. */ | 13 | * LHREQ_BREAK and the value "1" to /dev/lguest to do this. Once the Launcher |
14 | * has done whatever needs attention, it writes LHREQ_BREAK and "0" to release | ||
15 | * the Waker. */ | ||
14 | static int break_guest_out(struct lguest *lg, const unsigned long __user *input) | 16 | static int break_guest_out(struct lguest *lg, const unsigned long __user *input) |
15 | { | 17 | { |
16 | unsigned long on; | 18 | unsigned long on; |
17 | 19 | ||
18 | /* Fetch whether they're turning break on or off.. */ | 20 | /* Fetch whether they're turning break on or off. */ |
19 | if (get_user(on, input) != 0) | 21 | if (get_user(on, input) != 0) |
20 | return -EFAULT; | 22 | return -EFAULT; |
21 | 23 | ||
22 | if (on) { | 24 | if (on) { |
23 | lg->break_out = 1; | 25 | lg->break_out = 1; |
24 | /* Pop it out (may be running on different CPU) */ | 26 | /* Pop it out of the Guest (may be running on different CPU) */ |
25 | wake_up_process(lg->tsk); | 27 | wake_up_process(lg->tsk); |
26 | /* Wait for them to reset it */ | 28 | /* Wait for them to reset it */ |
27 | return wait_event_interruptible(lg->break_wq, !lg->break_out); | 29 | return wait_event_interruptible(lg->break_wq, !lg->break_out); |
@@ -58,7 +60,7 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) | |||
58 | if (!lg) | 60 | if (!lg) |
59 | return -EINVAL; | 61 | return -EINVAL; |
60 | 62 | ||
61 | /* If you're not the task which owns the guest, go away. */ | 63 | /* If you're not the task which owns the Guest, go away. */ |
62 | if (current != lg->tsk) | 64 | if (current != lg->tsk) |
63 | return -EPERM; | 65 | return -EPERM; |
64 | 66 | ||
@@ -92,8 +94,8 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) | |||
92 | * base: The start of the Guest-physical memory inside the Launcher memory. | 94 | * base: The start of the Guest-physical memory inside the Launcher memory. |
93 | * | 95 | * |
94 | * pfnlimit: The highest (Guest-physical) page number the Guest should be | 96 | * pfnlimit: The highest (Guest-physical) page number the Guest should be |
95 | * allowed to access. The Launcher has to live in Guest memory, so it sets | 97 | * allowed to access. The Guest memory lives inside the Launcher, so it sets |
96 | * this to ensure the Guest can't reach it. | 98 | * this to ensure the Guest can only reach its own memory. |
97 | * | 99 | * |
98 | * pgdir: The (Guest-physical) address of the top of the initial Guest | 100 | * pgdir: The (Guest-physical) address of the top of the initial Guest |
99 | * pagetables (which are set up by the Launcher). | 101 | * pagetables (which are set up by the Launcher). |
@@ -189,7 +191,7 @@ unlock: | |||
189 | } | 191 | } |
190 | 192 | ||
191 | /*L:010 The first operation the Launcher does must be a write. All writes | 193 | /*L:010 The first operation the Launcher does must be a write. All writes |
192 | * start with a 32 bit number: for the first write this must be | 194 | * start with an unsigned long number: for the first write this must be |
193 | * LHREQ_INITIALIZE to set up the Guest. After that the Launcher can use | 195 | * LHREQ_INITIALIZE to set up the Guest. After that the Launcher can use |
194 | * writes of other values to send interrupts. */ | 196 | * writes of other values to send interrupts. */ |
195 | static ssize_t write(struct file *file, const char __user *in, | 197 | static ssize_t write(struct file *file, const char __user *in, |
@@ -275,8 +277,7 @@ static int close(struct inode *inode, struct file *file) | |||
275 | * The Launcher is the Host userspace program which sets up, runs and services | 277 | * The Launcher is the Host userspace program which sets up, runs and services |
276 | * the Guest. In fact, many comments in the Drivers which refer to "the Host" | 278 | * the Guest. In fact, many comments in the Drivers which refer to "the Host" |
277 | * doing things are inaccurate: the Launcher does all the device handling for | 279 | * doing things are inaccurate: the Launcher does all the device handling for |
278 | * the Guest. The Guest can't tell what's done by the the Launcher and what by | 280 | * the Guest, but the Guest can't know that. |
279 | * the Host. | ||
280 | * | 281 | * |
281 | * Just to confuse you: to the Host kernel, the Launcher *is* the Guest and we | 282 | * Just to confuse you: to the Host kernel, the Launcher *is* the Guest and we |
282 | * shall see more of that later. | 283 | * shall see more of that later. |
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 2a45f0691c9b..fffabb327157 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
@@ -26,7 +26,8 @@ | |||
26 | * | 26 | * |
27 | * We use two-level page tables for the Guest. If you're not entirely | 27 | * We use two-level page tables for the Guest. If you're not entirely |
28 | * comfortable with virtual addresses, physical addresses and page tables then | 28 | * comfortable with virtual addresses, physical addresses and page tables then |
29 | * I recommend you review lguest.c's "Page Table Handling" (with diagrams!). | 29 | * I recommend you review arch/x86/lguest/boot.c's "Page Table Handling" (with |
30 | * diagrams!). | ||
30 | * | 31 | * |
31 | * The Guest keeps page tables, but we maintain the actual ones here: these are | 32 | * The Guest keeps page tables, but we maintain the actual ones here: these are |
32 | * called "shadow" page tables. Which is a very Guest-centric name: these are | 33 | * called "shadow" page tables. Which is a very Guest-centric name: these are |
@@ -36,11 +37,11 @@ | |||
36 | * | 37 | * |
37 | * Anyway, this is the most complicated part of the Host code. There are seven | 38 | * Anyway, this is the most complicated part of the Host code. There are seven |
38 | * parts to this: | 39 | * parts to this: |
39 | * (i) Setting up a page table entry for the Guest when it faults, | 40 | * (i) Looking up a page table entry when the Guest faults, |
40 | * (ii) Setting up the page table entry for the Guest stack, | 41 | * (ii) Making sure the Guest stack is mapped, |
41 | * (iii) Setting up a page table entry when the Guest tells us it has changed, | 42 | * (iii) Setting up a page table entry when the Guest tells us one has changed, |
42 | * (iv) Switching page tables, | 43 | * (iv) Switching page tables, |
43 | * (v) Flushing (thowing away) page tables, | 44 | * (v) Flushing (throwing away) page tables, |
44 | * (vi) Mapping the Switcher when the Guest is about to run, | 45 | * (vi) Mapping the Switcher when the Guest is about to run, |
45 | * (vii) Setting up the page tables initially. | 46 | * (vii) Setting up the page tables initially. |
46 | :*/ | 47 | :*/ |
@@ -57,16 +58,15 @@ | |||
57 | static DEFINE_PER_CPU(pte_t *, switcher_pte_pages); | 58 | static DEFINE_PER_CPU(pte_t *, switcher_pte_pages); |
58 | #define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu) | 59 | #define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu) |
59 | 60 | ||
60 | /*H:320 With our shadow and Guest types established, we need to deal with | 61 | /*H:320 The page table code is curly enough to need helper functions to keep it |
61 | * them: the page table code is curly enough to need helper functions to keep | 62 | * clear and clean. |
62 | * it clear and clean. | ||
63 | * | 63 | * |
64 | * There are two functions which return pointers to the shadow (aka "real") | 64 | * There are two functions which return pointers to the shadow (aka "real") |
65 | * page tables. | 65 | * page tables. |
66 | * | 66 | * |
67 | * spgd_addr() takes the virtual address and returns a pointer to the top-level | 67 | * spgd_addr() takes the virtual address and returns a pointer to the top-level |
68 | * page directory entry for that address. Since we keep track of several page | 68 | * page directory entry (PGD) for that address. Since we keep track of several |
69 | * tables, the "i" argument tells us which one we're interested in (it's | 69 | * page tables, the "i" argument tells us which one we're interested in (it's |
70 | * usually the current one). */ | 70 | * usually the current one). */ |
71 | static pgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr) | 71 | static pgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr) |
72 | { | 72 | { |
@@ -81,9 +81,9 @@ static pgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr) | |||
81 | return &lg->pgdirs[i].pgdir[index]; | 81 | return &lg->pgdirs[i].pgdir[index]; |
82 | } | 82 | } |
83 | 83 | ||
84 | /* This routine then takes the PGD entry given above, which contains the | 84 | /* This routine then takes the page directory entry returned above, which |
85 | * address of the PTE page. It then returns a pointer to the PTE entry for the | 85 | * contains the address of the page table entry (PTE) page. It then returns a |
86 | * given address. */ | 86 | * pointer to the PTE entry for the given address. */ |
87 | static pte_t *spte_addr(struct lguest *lg, pgd_t spgd, unsigned long vaddr) | 87 | static pte_t *spte_addr(struct lguest *lg, pgd_t spgd, unsigned long vaddr) |
88 | { | 88 | { |
89 | pte_t *page = __va(pgd_pfn(spgd) << PAGE_SHIFT); | 89 | pte_t *page = __va(pgd_pfn(spgd) << PAGE_SHIFT); |
@@ -191,7 +191,7 @@ static void check_gpgd(struct lguest *lg, pgd_t gpgd) | |||
191 | } | 191 | } |
192 | 192 | ||
193 | /*H:330 | 193 | /*H:330 |
194 | * (i) Setting up a page table entry for the Guest when it faults | 194 | * (i) Looking up a page table entry when the Guest faults. |
195 | * | 195 | * |
196 | * We saw this call in run_guest(): when we see a page fault in the Guest, we | 196 | * We saw this call in run_guest(): when we see a page fault in the Guest, we |
197 | * come here. That's because we only set up the shadow page tables lazily as | 197 | * come here. That's because we only set up the shadow page tables lazily as |
@@ -199,7 +199,7 @@ static void check_gpgd(struct lguest *lg, pgd_t gpgd) | |||
199 | * and return to the Guest without it knowing. | 199 | * and return to the Guest without it knowing. |
200 | * | 200 | * |
201 | * If we fixed up the fault (ie. we mapped the address), this routine returns | 201 | * If we fixed up the fault (ie. we mapped the address), this routine returns |
202 | * true. */ | 202 | * true. Otherwise, it was a real fault and we need to tell the Guest. */ |
203 | int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) | 203 | int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) |
204 | { | 204 | { |
205 | pgd_t gpgd; | 205 | pgd_t gpgd; |
@@ -246,16 +246,16 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) | |||
246 | if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW)) | 246 | if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW)) |
247 | return 0; | 247 | return 0; |
248 | 248 | ||
249 | /* User access to a kernel page? (bit 3 == user access) */ | 249 | /* User access to a kernel-only page? (bit 3 == user access) */ |
250 | if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER)) | 250 | if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER)) |
251 | return 0; | 251 | return 0; |
252 | 252 | ||
253 | /* Check that the Guest PTE flags are OK, and the page number is below | 253 | /* Check that the Guest PTE flags are OK, and the page number is below |
254 | * the pfn_limit (ie. not mapping the Launcher binary). */ | 254 | * the pfn_limit (ie. not mapping the Launcher binary). */ |
255 | check_gpte(lg, gpte); | 255 | check_gpte(lg, gpte); |
256 | |||
256 | /* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */ | 257 | /* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */ |
257 | gpte = pte_mkyoung(gpte); | 258 | gpte = pte_mkyoung(gpte); |
258 | |||
259 | if (errcode & 2) | 259 | if (errcode & 2) |
260 | gpte = pte_mkdirty(gpte); | 260 | gpte = pte_mkdirty(gpte); |
261 | 261 | ||
@@ -272,23 +272,28 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) | |||
272 | else | 272 | else |
273 | /* If this is a read, don't set the "writable" bit in the page | 273 | /* If this is a read, don't set the "writable" bit in the page |
274 | * table entry, even if the Guest says it's writable. That way | 274 | * table entry, even if the Guest says it's writable. That way |
275 | * we come back here when a write does actually ocur, so we can | 275 | * we will come back here when a write does actually occur, so |
276 | * update the Guest's _PAGE_DIRTY flag. */ | 276 | * we can update the Guest's _PAGE_DIRTY flag. */ |
277 | *spte = gpte_to_spte(lg, pte_wrprotect(gpte), 0); | 277 | *spte = gpte_to_spte(lg, pte_wrprotect(gpte), 0); |
278 | 278 | ||
279 | /* Finally, we write the Guest PTE entry back: we've set the | 279 | /* Finally, we write the Guest PTE entry back: we've set the |
280 | * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */ | 280 | * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */ |
281 | lgwrite(lg, gpte_ptr, pte_t, gpte); | 281 | lgwrite(lg, gpte_ptr, pte_t, gpte); |
282 | 282 | ||
283 | /* We succeeded in mapping the page! */ | 283 | /* The fault is fixed, the page table is populated, the mapping |
284 | * manipulated, the result returned and the code complete. A small | ||
285 | * delay and a trace of alliteration are the only indications the Guest | ||
286 | * has that a page fault occurred at all. */ | ||
284 | return 1; | 287 | return 1; |
285 | } | 288 | } |
286 | 289 | ||
287 | /*H:360 (ii) Setting up the page table entry for the Guest stack. | 290 | /*H:360 |
291 | * (ii) Making sure the Guest stack is mapped. | ||
288 | * | 292 | * |
289 | * Remember pin_stack_pages() which makes sure the stack is mapped? It could | 293 | * Remember that direct traps into the Guest need a mapped Guest kernel stack. |
290 | * simply call demand_page(), but as we've seen that logic is quite long, and | 294 | * pin_stack_pages() calls us here: we could simply call demand_page(), but as |
291 | * usually the stack pages are already mapped anyway, so it's not required. | 295 | * we've seen that logic is quite long, and usually the stack pages are already |
296 | * mapped, so it's overkill. | ||
292 | * | 297 | * |
293 | * This is a quick version which answers the question: is this virtual address | 298 | * This is a quick version which answers the question: is this virtual address |
294 | * mapped by the shadow page tables, and is it writable? */ | 299 | * mapped by the shadow page tables, and is it writable? */ |
@@ -297,7 +302,7 @@ static int page_writable(struct lguest *lg, unsigned long vaddr) | |||
297 | pgd_t *spgd; | 302 | pgd_t *spgd; |
298 | unsigned long flags; | 303 | unsigned long flags; |
299 | 304 | ||
300 | /* Look at the top level entry: is it present? */ | 305 | /* Look at the current top level entry: is it present? */ |
301 | spgd = spgd_addr(lg, lg->pgdidx, vaddr); | 306 | spgd = spgd_addr(lg, lg->pgdidx, vaddr); |
302 | if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) | 307 | if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) |
303 | return 0; | 308 | return 0; |
@@ -333,15 +338,14 @@ static void release_pgd(struct lguest *lg, pgd_t *spgd) | |||
333 | release_pte(ptepage[i]); | 338 | release_pte(ptepage[i]); |
334 | /* Now we can free the page of PTEs */ | 339 | /* Now we can free the page of PTEs */ |
335 | free_page((long)ptepage); | 340 | free_page((long)ptepage); |
336 | /* And zero out the PGD entry we we never release it twice. */ | 341 | /* And zero out the PGD entry so we never release it twice. */ |
337 | *spgd = __pgd(0); | 342 | *spgd = __pgd(0); |
338 | } | 343 | } |
339 | } | 344 | } |
340 | 345 | ||
341 | /*H:440 (v) Flushing (thowing away) page tables, | 346 | /*H:445 We saw flush_user_mappings() twice: once from the flush_user_mappings() |
342 | * | 347 | * hypercall and once in new_pgdir() when we re-used a top-level pgdir page. |
343 | * We saw flush_user_mappings() called when we re-used a top-level pgdir page. | 348 | * It simply releases every PTE page from 0 up to the Guest's kernel address. */ |
344 | * It simply releases every PTE page from 0 up to the kernel address. */ | ||
345 | static void flush_user_mappings(struct lguest *lg, int idx) | 349 | static void flush_user_mappings(struct lguest *lg, int idx) |
346 | { | 350 | { |
347 | unsigned int i; | 351 | unsigned int i; |
@@ -350,8 +354,10 @@ static void flush_user_mappings(struct lguest *lg, int idx) | |||
350 | release_pgd(lg, lg->pgdirs[idx].pgdir + i); | 354 | release_pgd(lg, lg->pgdirs[idx].pgdir + i); |
351 | } | 355 | } |
352 | 356 | ||
353 | /* The Guest also has a hypercall to do this manually: it's used when a large | 357 | /*H:440 (v) Flushing (throwing away) page tables, |
354 | * number of mappings have been changed. */ | 358 | * |
359 | * The Guest has a hypercall to throw away the page tables: it's used when a | ||
360 | * large number of mappings have been changed. */ | ||
355 | void guest_pagetable_flush_user(struct lguest *lg) | 361 | void guest_pagetable_flush_user(struct lguest *lg) |
356 | { | 362 | { |
357 | /* Drop the userspace part of the current page table. */ | 363 | /* Drop the userspace part of the current page table. */ |
@@ -423,8 +429,9 @@ static unsigned int new_pgdir(struct lguest *lg, | |||
423 | 429 | ||
424 | /*H:430 (iv) Switching page tables | 430 | /*H:430 (iv) Switching page tables |
425 | * | 431 | * |
426 | * This is what happens when the Guest changes page tables (ie. changes the | 432 | * Now we've seen all the page table setting and manipulation, let's see what |
427 | * top-level pgdir). This happens on almost every context switch. */ | 433 | * what happens when the Guest changes page tables (ie. changes the top-level |
434 | * pgdir). This occurs on almost every context switch. */ | ||
428 | void guest_new_pagetable(struct lguest *lg, unsigned long pgtable) | 435 | void guest_new_pagetable(struct lguest *lg, unsigned long pgtable) |
429 | { | 436 | { |
430 | int newpgdir, repin = 0; | 437 | int newpgdir, repin = 0; |
@@ -443,7 +450,8 @@ void guest_new_pagetable(struct lguest *lg, unsigned long pgtable) | |||
443 | } | 450 | } |
444 | 451 | ||
445 | /*H:470 Finally, a routine which throws away everything: all PGD entries in all | 452 | /*H:470 Finally, a routine which throws away everything: all PGD entries in all |
446 | * the shadow page tables. This is used when we destroy the Guest. */ | 453 | * the shadow page tables, including the Guest's kernel mappings. This is used |
454 | * when we destroy the Guest. */ | ||
447 | static void release_all_pagetables(struct lguest *lg) | 455 | static void release_all_pagetables(struct lguest *lg) |
448 | { | 456 | { |
449 | unsigned int i, j; | 457 | unsigned int i, j; |
@@ -458,13 +466,22 @@ static void release_all_pagetables(struct lguest *lg) | |||
458 | 466 | ||
459 | /* We also throw away everything when a Guest tells us it's changed a kernel | 467 | /* We also throw away everything when a Guest tells us it's changed a kernel |
460 | * mapping. Since kernel mappings are in every page table, it's easiest to | 468 | * mapping. Since kernel mappings are in every page table, it's easiest to |
461 | * throw them all away. This is amazingly slow, but thankfully rare. */ | 469 | * throw them all away. This traps the Guest in amber for a while as |
470 | * everything faults back in, but it's rare. */ | ||
462 | void guest_pagetable_clear_all(struct lguest *lg) | 471 | void guest_pagetable_clear_all(struct lguest *lg) |
463 | { | 472 | { |
464 | release_all_pagetables(lg); | 473 | release_all_pagetables(lg); |
465 | /* We need the Guest kernel stack mapped again. */ | 474 | /* We need the Guest kernel stack mapped again. */ |
466 | pin_stack_pages(lg); | 475 | pin_stack_pages(lg); |
467 | } | 476 | } |
477 | /*:*/ | ||
478 | /*M:009 Since we throw away all mappings when a kernel mapping changes, our | ||
479 | * performance sucks for guests using highmem. In fact, a guest with | ||
480 | * PAGE_OFFSET 0xc0000000 (the default) and more than about 700MB of RAM is | ||
481 | * usually slower than a Guest with less memory. | ||
482 | * | ||
483 | * This, of course, cannot be fixed. It would take some kind of... well, I | ||
484 | * don't know, but the term "puissant code-fu" comes to mind. :*/ | ||
468 | 485 | ||
469 | /*H:420 This is the routine which actually sets the page table entry for then | 486 | /*H:420 This is the routine which actually sets the page table entry for then |
470 | * "idx"'th shadow page table. | 487 | * "idx"'th shadow page table. |
@@ -483,7 +500,7 @@ void guest_pagetable_clear_all(struct lguest *lg) | |||
483 | static void do_set_pte(struct lguest *lg, int idx, | 500 | static void do_set_pte(struct lguest *lg, int idx, |
484 | unsigned long vaddr, pte_t gpte) | 501 | unsigned long vaddr, pte_t gpte) |
485 | { | 502 | { |
486 | /* Look up the matching shadow page directot entry. */ | 503 | /* Look up the matching shadow page directory entry. */ |
487 | pgd_t *spgd = spgd_addr(lg, idx, vaddr); | 504 | pgd_t *spgd = spgd_addr(lg, idx, vaddr); |
488 | 505 | ||
489 | /* If the top level isn't present, there's no entry to update. */ | 506 | /* If the top level isn't present, there's no entry to update. */ |
@@ -500,7 +517,8 @@ static void do_set_pte(struct lguest *lg, int idx, | |||
500 | *spte = gpte_to_spte(lg, gpte, | 517 | *spte = gpte_to_spte(lg, gpte, |
501 | pte_flags(gpte) & _PAGE_DIRTY); | 518 | pte_flags(gpte) & _PAGE_DIRTY); |
502 | } else | 519 | } else |
503 | /* Otherwise we can demand_page() it in later. */ | 520 | /* Otherwise kill it and we can demand_page() it in |
521 | * later. */ | ||
504 | *spte = __pte(0); | 522 | *spte = __pte(0); |
505 | } | 523 | } |
506 | } | 524 | } |
@@ -535,7 +553,7 @@ void guest_set_pte(struct lguest *lg, | |||
535 | } | 553 | } |
536 | 554 | ||
537 | /*H:400 | 555 | /*H:400 |
538 | * (iii) Setting up a page table entry when the Guest tells us it has changed. | 556 | * (iii) Setting up a page table entry when the Guest tells us one has changed. |
539 | * | 557 | * |
540 | * Just like we did in interrupts_and_traps.c, it makes sense for us to deal | 558 | * Just like we did in interrupts_and_traps.c, it makes sense for us to deal |
541 | * with the other side of page tables while we're here: what happens when the | 559 | * with the other side of page tables while we're here: what happens when the |
@@ -612,9 +630,10 @@ void free_guest_pagetable(struct lguest *lg) | |||
612 | 630 | ||
613 | /*H:480 (vi) Mapping the Switcher when the Guest is about to run. | 631 | /*H:480 (vi) Mapping the Switcher when the Guest is about to run. |
614 | * | 632 | * |
615 | * The Switcher and the two pages for this CPU need to be available to the | 633 | * The Switcher and the two pages for this CPU need to be visible in the |
616 | * Guest (and not the pages for other CPUs). We have the appropriate PTE pages | 634 | * Guest (and not the pages for other CPUs). We have the appropriate PTE pages |
617 | * for each CPU already set up, we just need to hook them in. */ | 635 | * for each CPU already set up, we just need to hook them in now we know which |
636 | * Guest is about to run on this CPU. */ | ||
618 | void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages) | 637 | void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages) |
619 | { | 638 | { |
620 | pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); | 639 | pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); |
@@ -677,6 +696,18 @@ static __init void populate_switcher_pte_page(unsigned int cpu, | |||
677 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED)); | 696 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED)); |
678 | } | 697 | } |
679 | 698 | ||
699 | /* We've made it through the page table code. Perhaps our tired brains are | ||
700 | * still processing the details, or perhaps we're simply glad it's over. | ||
701 | * | ||
702 | * If nothing else, note that all this complexity in juggling shadow page | ||
703 | * tables in sync with the Guest's page tables is for one reason: for most | ||
704 | * Guests this page table dance determines how bad performance will be. This | ||
705 | * is why Xen uses exotic direct Guest pagetable manipulation, and why both | ||
706 | * Intel and AMD have implemented shadow page table support directly into | ||
707 | * hardware. | ||
708 | * | ||
709 | * There is just one file remaining in the Host. */ | ||
710 | |||
680 | /*H:510 At boot or module load time, init_pagetables() allocates and populates | 711 | /*H:510 At boot or module load time, init_pagetables() allocates and populates |
681 | * the Switcher PTE page for each CPU. */ | 712 | * the Switcher PTE page for each CPU. */ |
682 | __init int init_pagetables(struct page **switcher_page, unsigned int pages) | 713 | __init int init_pagetables(struct page **switcher_page, unsigned int pages) |
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c index c2434ec99f7b..9e189cbec7dd 100644 --- a/drivers/lguest/segments.c +++ b/drivers/lguest/segments.c | |||
@@ -12,8 +12,6 @@ | |||
12 | #include "lg.h" | 12 | #include "lg.h" |
13 | 13 | ||
14 | /*H:600 | 14 | /*H:600 |
15 | * We've almost completed the Host; there's just one file to go! | ||
16 | * | ||
17 | * Segments & The Global Descriptor Table | 15 | * Segments & The Global Descriptor Table |
18 | * | 16 | * |
19 | * (That title sounds like a bad Nerdcore group. Not to suggest that there are | 17 | * (That title sounds like a bad Nerdcore group. Not to suggest that there are |
@@ -55,7 +53,7 @@ static int ignored_gdt(unsigned int num) | |||
55 | || num == GDT_ENTRY_DOUBLEFAULT_TSS); | 53 | || num == GDT_ENTRY_DOUBLEFAULT_TSS); |
56 | } | 54 | } |
57 | 55 | ||
58 | /*H:610 Once the GDT has been changed, we fix the new entries up a little. We | 56 | /*H:630 Once the Guest gave us new GDT entries, we fix them up a little. We |
59 | * don't care if they're invalid: the worst that can happen is a General | 57 | * don't care if they're invalid: the worst that can happen is a General |
60 | * Protection Fault in the Switcher when it restores a Guest segment register | 58 | * Protection Fault in the Switcher when it restores a Guest segment register |
61 | * which tries to use that entry. Then we kill the Guest for causing such a | 59 | * which tries to use that entry. Then we kill the Guest for causing such a |
@@ -84,25 +82,33 @@ static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end) | |||
84 | } | 82 | } |
85 | } | 83 | } |
86 | 84 | ||
87 | /* This routine is called at boot or modprobe time for each CPU to set up the | 85 | /*H:610 Like the IDT, we never simply use the GDT the Guest gives us. We keep |
88 | * "constant" GDT entries for Guests running on that CPU. */ | 86 | * a GDT for each CPU, and copy across the Guest's entries each time we want to |
87 | * run the Guest on that CPU. | ||
88 | * | ||
89 | * This routine is called at boot or modprobe time for each CPU to set up the | ||
90 | * constant GDT entries: the ones which are the same no matter what Guest we're | ||
91 | * running. */ | ||
89 | void setup_default_gdt_entries(struct lguest_ro_state *state) | 92 | void setup_default_gdt_entries(struct lguest_ro_state *state) |
90 | { | 93 | { |
91 | struct desc_struct *gdt = state->guest_gdt; | 94 | struct desc_struct *gdt = state->guest_gdt; |
92 | unsigned long tss = (unsigned long)&state->guest_tss; | 95 | unsigned long tss = (unsigned long)&state->guest_tss; |
93 | 96 | ||
94 | /* The hypervisor segments are full 0-4G segments, privilege level 0 */ | 97 | /* The Switcher segments are full 0-4G segments, privilege level 0 */ |
95 | gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT; | 98 | gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT; |
96 | gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT; | 99 | gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT; |
97 | 100 | ||
98 | /* The TSS segment refers to the TSS entry for this CPU, so we cannot | 101 | /* The TSS segment refers to the TSS entry for this particular CPU. |
99 | * copy it from the Guest. Forgive the magic flags */ | 102 | * Forgive the magic flags: the 0x8900 means the entry is Present, it's |
103 | * privilege level 0 Available 386 TSS system segment, and the 0x67 | ||
104 | * means Saturn is eclipsed by Mercury in the twelfth house. */ | ||
100 | gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16); | 105 | gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16); |
101 | gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000) | 106 | gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000) |
102 | | ((tss >> 16) & 0x000000FF); | 107 | | ((tss >> 16) & 0x000000FF); |
103 | } | 108 | } |
104 | 109 | ||
105 | /* This routine is called before the Guest is run for the first time. */ | 110 | /* This routine sets up the initial Guest GDT for booting. All entries start |
111 | * as 0 (unusable). */ | ||
106 | void setup_guest_gdt(struct lguest *lg) | 112 | void setup_guest_gdt(struct lguest *lg) |
107 | { | 113 | { |
108 | /* Start with full 0-4G segments... */ | 114 | /* Start with full 0-4G segments... */ |
@@ -114,13 +120,8 @@ void setup_guest_gdt(struct lguest *lg) | |||
114 | lg->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13); | 120 | lg->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13); |
115 | } | 121 | } |
116 | 122 | ||
117 | /* Like the IDT, we never simply use the GDT the Guest gives us. We set up the | 123 | /*H:650 An optimization of copy_gdt(), for just the three "thead-local storage" |
118 | * GDTs for each CPU, then we copy across the entries each time we want to run | 124 | * entries. */ |
119 | * a different Guest on that CPU. */ | ||
120 | |||
121 | /* A partial GDT load, for the three "thead-local storage" entries. Otherwise | ||
122 | * it's just like load_guest_gdt(). So much, in fact, it would probably be | ||
123 | * neater to have a single hypercall to cover both. */ | ||
124 | void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt) | 125 | void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt) |
125 | { | 126 | { |
126 | unsigned int i; | 127 | unsigned int i; |
@@ -129,7 +130,9 @@ void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt) | |||
129 | gdt[i] = lg->arch.gdt[i]; | 130 | gdt[i] = lg->arch.gdt[i]; |
130 | } | 131 | } |
131 | 132 | ||
132 | /* This is the full version */ | 133 | /*H:640 When the Guest is run on a different CPU, or the GDT entries have |
134 | * changed, copy_gdt() is called to copy the Guest's GDT entries across to this | ||
135 | * CPU's GDT. */ | ||
133 | void copy_gdt(const struct lguest *lg, struct desc_struct *gdt) | 136 | void copy_gdt(const struct lguest *lg, struct desc_struct *gdt) |
134 | { | 137 | { |
135 | unsigned int i; | 138 | unsigned int i; |
@@ -141,7 +144,8 @@ void copy_gdt(const struct lguest *lg, struct desc_struct *gdt) | |||
141 | gdt[i] = lg->arch.gdt[i]; | 144 | gdt[i] = lg->arch.gdt[i]; |
142 | } | 145 | } |
143 | 146 | ||
144 | /* This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). */ | 147 | /*H:620 This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). |
148 | * We copy it from the Guest and tweak the entries. */ | ||
145 | void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num) | 149 | void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num) |
146 | { | 150 | { |
147 | /* We assume the Guest has the same number of GDT entries as the | 151 | /* We assume the Guest has the same number of GDT entries as the |
@@ -157,16 +161,22 @@ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num) | |||
157 | lg->changed |= CHANGED_GDT; | 161 | lg->changed |= CHANGED_GDT; |
158 | } | 162 | } |
159 | 163 | ||
164 | /* This is the fast-track version for just changing the three TLS entries. | ||
165 | * Remember that this happens on every context switch, so it's worth | ||
166 | * optimizing. But wouldn't it be neater to have a single hypercall to cover | ||
167 | * both cases? */ | ||
160 | void guest_load_tls(struct lguest *lg, unsigned long gtls) | 168 | void guest_load_tls(struct lguest *lg, unsigned long gtls) |
161 | { | 169 | { |
162 | struct desc_struct *tls = &lg->arch.gdt[GDT_ENTRY_TLS_MIN]; | 170 | struct desc_struct *tls = &lg->arch.gdt[GDT_ENTRY_TLS_MIN]; |
163 | 171 | ||
164 | __lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES); | 172 | __lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES); |
165 | fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1); | 173 | fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1); |
174 | /* Note that just the TLS entries have changed. */ | ||
166 | lg->changed |= CHANGED_GDT_TLS; | 175 | lg->changed |= CHANGED_GDT_TLS; |
167 | } | 176 | } |
177 | /*:*/ | ||
168 | 178 | ||
169 | /* | 179 | /*H:660 |
170 | * With this, we have finished the Host. | 180 | * With this, we have finished the Host. |
171 | * | 181 | * |
172 | * Five of the seven parts of our task are complete. You have made it through | 182 | * Five of the seven parts of our task are complete. You have made it through |
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 09d9207420dc..482aec2a9631 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c | |||
@@ -63,7 +63,7 @@ static struct lguest_pages *lguest_pages(unsigned int cpu) | |||
63 | static DEFINE_PER_CPU(struct lguest *, last_guest); | 63 | static DEFINE_PER_CPU(struct lguest *, last_guest); |
64 | 64 | ||
65 | /*S:010 | 65 | /*S:010 |
66 | * We are getting close to the Switcher. | 66 | * We approach the Switcher. |
67 | * | 67 | * |
68 | * Remember that each CPU has two pages which are visible to the Guest when it | 68 | * Remember that each CPU has two pages which are visible to the Guest when it |
69 | * runs on that CPU. This has to contain the state for that Guest: we copy the | 69 | * runs on that CPU. This has to contain the state for that Guest: we copy the |
@@ -134,7 +134,7 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages) | |||
134 | * | 134 | * |
135 | * The lcall also pushes the old code segment (KERNEL_CS) onto the | 135 | * The lcall also pushes the old code segment (KERNEL_CS) onto the |
136 | * stack, then the address of this call. This stack layout happens to | 136 | * stack, then the address of this call. This stack layout happens to |
137 | * exactly match the stack of an interrupt... */ | 137 | * exactly match the stack layout created by an interrupt... */ |
138 | asm volatile("pushf; lcall *lguest_entry" | 138 | asm volatile("pushf; lcall *lguest_entry" |
139 | /* This is how we tell GCC that %eax ("a") and %ebx ("b") | 139 | /* This is how we tell GCC that %eax ("a") and %ebx ("b") |
140 | * are changed by this routine. The "=" means output. */ | 140 | * are changed by this routine. The "=" means output. */ |
@@ -151,40 +151,46 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages) | |||
151 | } | 151 | } |
152 | /*:*/ | 152 | /*:*/ |
153 | 153 | ||
154 | /*M:002 There are hooks in the scheduler which we can register to tell when we | ||
155 | * get kicked off the CPU (preempt_notifier_register()). This would allow us | ||
156 | * to lazily disable SYSENTER which would regain some performance, and should | ||
157 | * also simplify copy_in_guest_info(). Note that we'd still need to restore | ||
158 | * things when we exit to Launcher userspace, but that's fairly easy. | ||
159 | * | ||
160 | * The hooks were designed for KVM, but we can also put them to good use. :*/ | ||
161 | |||
154 | /*H:040 This is the i386-specific code to setup and run the Guest. Interrupts | 162 | /*H:040 This is the i386-specific code to setup and run the Guest. Interrupts |
155 | * are disabled: we own the CPU. */ | 163 | * are disabled: we own the CPU. */ |
156 | void lguest_arch_run_guest(struct lguest *lg) | 164 | void lguest_arch_run_guest(struct lguest *lg) |
157 | { | 165 | { |
158 | /* Remember the awfully-named TS bit? If the Guest has asked | 166 | /* Remember the awfully-named TS bit? If the Guest has asked to set it |
159 | * to set it we set it now, so we can trap and pass that trap | 167 | * we set it now, so we can trap and pass that trap to the Guest if it |
160 | * to the Guest if it uses the FPU. */ | 168 | * uses the FPU. */ |
161 | if (lg->ts) | 169 | if (lg->ts) |
162 | lguest_set_ts(); | 170 | lguest_set_ts(); |
163 | 171 | ||
164 | /* SYSENTER is an optimized way of doing system calls. We | 172 | /* SYSENTER is an optimized way of doing system calls. We can't allow |
165 | * can't allow it because it always jumps to privilege level 0. | 173 | * it because it always jumps to privilege level 0. A normal Guest |
166 | * A normal Guest won't try it because we don't advertise it in | 174 | * won't try it because we don't advertise it in CPUID, but a malicious |
167 | * CPUID, but a malicious Guest (or malicious Guest userspace | 175 | * Guest (or malicious Guest userspace program) could, so we tell the |
168 | * program) could, so we tell the CPU to disable it before | 176 | * CPU to disable it before running the Guest. */ |
169 | * running the Guest. */ | ||
170 | if (boot_cpu_has(X86_FEATURE_SEP)) | 177 | if (boot_cpu_has(X86_FEATURE_SEP)) |
171 | wrmsr(MSR_IA32_SYSENTER_CS, 0, 0); | 178 | wrmsr(MSR_IA32_SYSENTER_CS, 0, 0); |
172 | 179 | ||
173 | /* Now we actually run the Guest. It will pop back out when | 180 | /* Now we actually run the Guest. It will return when something |
174 | * something interesting happens, and we can examine its | 181 | * interesting happens, and we can examine its registers to see what it |
175 | * registers to see what it was doing. */ | 182 | * was doing. */ |
176 | run_guest_once(lg, lguest_pages(raw_smp_processor_id())); | 183 | run_guest_once(lg, lguest_pages(raw_smp_processor_id())); |
177 | 184 | ||
178 | /* The "regs" pointer contains two extra entries which are not | 185 | /* Note that the "regs" pointer contains two extra entries which are |
179 | * really registers: a trap number which says what interrupt or | 186 | * not really registers: a trap number which says what interrupt or |
180 | * trap made the switcher code come back, and an error code | 187 | * trap made the switcher code come back, and an error code which some |
181 | * which some traps set. */ | 188 | * traps set. */ |
182 | 189 | ||
183 | /* If the Guest page faulted, then the cr2 register will tell | 190 | /* If the Guest page faulted, then the cr2 register will tell us the |
184 | * us the bad virtual address. We have to grab this now, | 191 | * bad virtual address. We have to grab this now, because once we |
185 | * because once we re-enable interrupts an interrupt could | 192 | * re-enable interrupts an interrupt could fault and thus overwrite |
186 | * fault and thus overwrite cr2, or we could even move off to a | 193 | * cr2, or we could even move off to a different CPU. */ |
187 | * different CPU. */ | ||
188 | if (lg->regs->trapnum == 14) | 194 | if (lg->regs->trapnum == 14) |
189 | lg->arch.last_pagefault = read_cr2(); | 195 | lg->arch.last_pagefault = read_cr2(); |
190 | /* Similarly, if we took a trap because the Guest used the FPU, | 196 | /* Similarly, if we took a trap because the Guest used the FPU, |
@@ -197,14 +203,15 @@ void lguest_arch_run_guest(struct lguest *lg) | |||
197 | wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); | 203 | wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); |
198 | } | 204 | } |
199 | 205 | ||
200 | /*H:130 Our Guest is usually so well behaved; it never tries to do things it | 206 | /*H:130 Now we've examined the hypercall code; our Guest can make requests. |
201 | * isn't allowed to. Unfortunately, Linux's paravirtual infrastructure isn't | 207 | * Our Guest is usually so well behaved; it never tries to do things it isn't |
202 | * quite complete, because it doesn't contain replacements for the Intel I/O | 208 | * allowed to, and uses hypercalls instead. Unfortunately, Linux's paravirtual |
203 | * instructions. As a result, the Guest sometimes fumbles across one during | 209 | * infrastructure isn't quite complete, because it doesn't contain replacements |
204 | * the boot process as it probes for various things which are usually attached | 210 | * for the Intel I/O instructions. As a result, the Guest sometimes fumbles |
205 | * to a PC. | 211 | * across one during the boot process as it probes for various things which are |
212 | * usually attached to a PC. | ||
206 | * | 213 | * |
207 | * When the Guest uses one of these instructions, we get trap #13 (General | 214 | * When the Guest uses one of these instructions, we get a trap (General |
208 | * Protection Fault) and come here. We see if it's one of those troublesome | 215 | * Protection Fault) and come here. We see if it's one of those troublesome |
209 | * instructions and skip over it. We return true if we did. */ | 216 | * instructions and skip over it. We return true if we did. */ |
210 | static int emulate_insn(struct lguest *lg) | 217 | static int emulate_insn(struct lguest *lg) |
@@ -275,43 +282,43 @@ static int emulate_insn(struct lguest *lg) | |||
275 | void lguest_arch_handle_trap(struct lguest *lg) | 282 | void lguest_arch_handle_trap(struct lguest *lg) |
276 | { | 283 | { |
277 | switch (lg->regs->trapnum) { | 284 | switch (lg->regs->trapnum) { |
278 | case 13: /* We've intercepted a GPF. */ | 285 | case 13: /* We've intercepted a General Protection Fault. */ |
279 | /* Check if this was one of those annoying IN or OUT | 286 | /* Check if this was one of those annoying IN or OUT |
280 | * instructions which we need to emulate. If so, we | 287 | * instructions which we need to emulate. If so, we just go |
281 | * just go back into the Guest after we've done it. */ | 288 | * back into the Guest after we've done it. */ |
282 | if (lg->regs->errcode == 0) { | 289 | if (lg->regs->errcode == 0) { |
283 | if (emulate_insn(lg)) | 290 | if (emulate_insn(lg)) |
284 | return; | 291 | return; |
285 | } | 292 | } |
286 | break; | 293 | break; |
287 | case 14: /* We've intercepted a page fault. */ | 294 | case 14: /* We've intercepted a Page Fault. */ |
288 | /* The Guest accessed a virtual address that wasn't | 295 | /* The Guest accessed a virtual address that wasn't mapped. |
289 | * mapped. This happens a lot: we don't actually set | 296 | * This happens a lot: we don't actually set up most of the |
290 | * up most of the page tables for the Guest at all when | 297 | * page tables for the Guest at all when we start: as it runs |
291 | * we start: as it runs it asks for more and more, and | 298 | * it asks for more and more, and we set them up as |
292 | * we set them up as required. In this case, we don't | 299 | * required. In this case, we don't even tell the Guest that |
293 | * even tell the Guest that the fault happened. | 300 | * the fault happened. |
294 | * | 301 | * |
295 | * The errcode tells whether this was a read or a | 302 | * The errcode tells whether this was a read or a write, and |
296 | * write, and whether kernel or userspace code. */ | 303 | * whether kernel or userspace code. */ |
297 | if (demand_page(lg, lg->arch.last_pagefault, lg->regs->errcode)) | 304 | if (demand_page(lg, lg->arch.last_pagefault, lg->regs->errcode)) |
298 | return; | 305 | return; |
299 | 306 | ||
300 | /* OK, it's really not there (or not OK): the Guest | 307 | /* OK, it's really not there (or not OK): the Guest needs to |
301 | * needs to know. We write out the cr2 value so it | 308 | * know. We write out the cr2 value so it knows where the |
302 | * knows where the fault occurred. | 309 | * fault occurred. |
303 | * | 310 | * |
304 | * Note that if the Guest were really messed up, this | 311 | * Note that if the Guest were really messed up, this could |
305 | * could happen before it's done the INITIALIZE | 312 | * happen before it's done the LHCALL_LGUEST_INIT hypercall, so |
306 | * hypercall, so lg->lguest_data will be NULL */ | 313 | * lg->lguest_data could be NULL */ |
307 | if (lg->lguest_data && | 314 | if (lg->lguest_data && |
308 | put_user(lg->arch.last_pagefault, &lg->lguest_data->cr2)) | 315 | put_user(lg->arch.last_pagefault, &lg->lguest_data->cr2)) |
309 | kill_guest(lg, "Writing cr2"); | 316 | kill_guest(lg, "Writing cr2"); |
310 | break; | 317 | break; |
311 | case 7: /* We've intercepted a Device Not Available fault. */ | 318 | case 7: /* We've intercepted a Device Not Available fault. */ |
312 | /* If the Guest doesn't want to know, we already | 319 | /* If the Guest doesn't want to know, we already restored the |
313 | * restored the Floating Point Unit, so we just | 320 | * Floating Point Unit, so we just continue without telling |
314 | * continue without telling it. */ | 321 | * it. */ |
315 | if (!lg->ts) | 322 | if (!lg->ts) |
316 | return; | 323 | return; |
317 | break; | 324 | break; |
@@ -536,9 +543,6 @@ int lguest_arch_init_hypercalls(struct lguest *lg) | |||
536 | 543 | ||
537 | return 0; | 544 | return 0; |
538 | } | 545 | } |
539 | /* Now we've examined the hypercall code; our Guest can make requests. There | ||
540 | * is one other way we can do things for the Guest, as we see in | ||
541 | * emulate_insn(). :*/ | ||
542 | 546 | ||
543 | /*L:030 lguest_arch_setup_regs() | 547 | /*L:030 lguest_arch_setup_regs() |
544 | * | 548 | * |
@@ -570,8 +574,8 @@ void lguest_arch_setup_regs(struct lguest *lg, unsigned long start) | |||
570 | 574 | ||
571 | /* %esi points to our boot information, at physical address 0, so don't | 575 | /* %esi points to our boot information, at physical address 0, so don't |
572 | * touch it. */ | 576 | * touch it. */ |
577 | |||
573 | /* There are a couple of GDT entries the Guest expects when first | 578 | /* There are a couple of GDT entries the Guest expects when first |
574 | * booting. */ | 579 | * booting. */ |
575 | |||
576 | setup_guest_gdt(lg); | 580 | setup_guest_gdt(lg); |
577 | } | 581 | } |
diff --git a/drivers/lguest/x86/switcher_32.S b/drivers/lguest/x86/switcher_32.S index 1010b90b11fc..0af8baaa0d4a 100644 --- a/drivers/lguest/x86/switcher_32.S +++ b/drivers/lguest/x86/switcher_32.S | |||
@@ -6,6 +6,37 @@ | |||
6 | * are feeling invigorated and refreshed then the next, more challenging stage | 6 | * are feeling invigorated and refreshed then the next, more challenging stage |
7 | * can be found in "make Guest". :*/ | 7 | * can be found in "make Guest". :*/ |
8 | 8 | ||
9 | /*M:012 Lguest is meant to be simple: my rule of thumb is that 1% more LOC must | ||
10 | * gain at least 1% more performance. Since neither LOC nor performance can be | ||
11 | * measured beforehand, it generally means implementing a feature then deciding | ||
12 | * if it's worth it. And once it's implemented, who can say no? | ||
13 | * | ||
14 | * This is why I haven't implemented this idea myself. I want to, but I | ||
15 | * haven't. You could, though. | ||
16 | * | ||
17 | * The main place where lguest performance sucks is Guest page faulting. When | ||
18 | * a Guest userspace process hits an unmapped page we switch back to the Host, | ||
19 | * walk the page tables, find it's not mapped, switch back to the Guest page | ||
20 | * fault handler, which calls a hypercall to set the page table entry, then | ||
21 | * finally returns to userspace. That's two round-trips. | ||
22 | * | ||
23 | * If we had a small walker in the Switcher, we could quickly check the Guest | ||
24 | * page table and if the page isn't mapped, immediately reflect the fault back | ||
25 | * into the Guest. This means the Switcher would have to know the top of the | ||
26 | * Guest page table and the page fault handler address. | ||
27 | * | ||
28 | * For simplicity, the Guest should only handle the case where the privilege | ||
29 | * level of the fault is 3 and probably only not present or write faults. It | ||
30 | * should also detect recursive faults, and hand the original fault to the | ||
31 | * Host (which is actually really easy). | ||
32 | * | ||
33 | * Two questions remain. Would the performance gain outweigh the complexity? | ||
34 | * And who would write the verse documenting it? :*/ | ||
35 | |||
36 | /*M:011 Lguest64 handles NMI. This gave me NMI envy (until I looked at their | ||
37 | * code). It's worth doing though, since it would let us use oprofile in the | ||
38 | * Host when a Guest is running. :*/ | ||
39 | |||
9 | /*S:100 | 40 | /*S:100 |
10 | * Welcome to the Switcher itself! | 41 | * Welcome to the Switcher itself! |
11 | * | 42 | * |
@@ -88,7 +119,7 @@ ENTRY(switch_to_guest) | |||
88 | 119 | ||
89 | // All saved and there's now five steps before us: | 120 | // All saved and there's now five steps before us: |
90 | // Stack, GDT, IDT, TSS | 121 | // Stack, GDT, IDT, TSS |
91 | // And last of all the page tables are flipped. | 122 | // Then last of all the page tables are flipped. |
92 | 123 | ||
93 | // Yet beware that our stack pointer must be | 124 | // Yet beware that our stack pointer must be |
94 | // Always valid lest an NMI hits | 125 | // Always valid lest an NMI hits |
@@ -103,25 +134,25 @@ ENTRY(switch_to_guest) | |||
103 | lgdt LGUEST_PAGES_guest_gdt_desc(%eax) | 134 | lgdt LGUEST_PAGES_guest_gdt_desc(%eax) |
104 | 135 | ||
105 | // The Guest's IDT we did partially | 136 | // The Guest's IDT we did partially |
106 | // Move to the "struct lguest_pages" as well. | 137 | // Copy to "struct lguest_pages" as well. |
107 | lidt LGUEST_PAGES_guest_idt_desc(%eax) | 138 | lidt LGUEST_PAGES_guest_idt_desc(%eax) |
108 | 139 | ||
109 | // The TSS entry which controls traps | 140 | // The TSS entry which controls traps |
110 | // Must be loaded up with "ltr" now: | 141 | // Must be loaded up with "ltr" now: |
142 | // The GDT entry that TSS uses | ||
143 | // Changes type when we load it: damn Intel! | ||
111 | // For after we switch over our page tables | 144 | // For after we switch over our page tables |
112 | // It (as the rest) will be writable no more. | 145 | // That entry will be read-only: we'd crash. |
113 | // (The GDT entry TSS needs | ||
114 | // Changes type when we load it: damn Intel!) | ||
115 | movl $(GDT_ENTRY_TSS*8), %edx | 146 | movl $(GDT_ENTRY_TSS*8), %edx |
116 | ltr %dx | 147 | ltr %dx |
117 | 148 | ||
118 | // Look back now, before we take this last step! | 149 | // Look back now, before we take this last step! |
119 | // The Host's TSS entry was also marked used; | 150 | // The Host's TSS entry was also marked used; |
120 | // Let's clear it again, ere we return. | 151 | // Let's clear it again for our return. |
121 | // The GDT descriptor of the Host | 152 | // The GDT descriptor of the Host |
122 | // Points to the table after two "size" bytes | 153 | // Points to the table after two "size" bytes |
123 | movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx | 154 | movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx |
124 | // Clear the type field of "used" (byte 5, bit 2) | 155 | // Clear "used" from type field (byte 5, bit 2) |
125 | andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx) | 156 | andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx) |
126 | 157 | ||
127 | // Once our page table's switched, the Guest is live! | 158 | // Once our page table's switched, the Guest is live! |
@@ -131,7 +162,7 @@ ENTRY(switch_to_guest) | |||
131 | 162 | ||
132 | // The page table change did one tricky thing: | 163 | // The page table change did one tricky thing: |
133 | // The Guest's register page has been mapped | 164 | // The Guest's register page has been mapped |
134 | // Writable onto our %esp (stack) -- | 165 | // Writable under our %esp (stack) -- |
135 | // We can simply pop off all Guest regs. | 166 | // We can simply pop off all Guest regs. |
136 | popl %eax | 167 | popl %eax |
137 | popl %ebx | 168 | popl %ebx |
@@ -152,16 +183,15 @@ ENTRY(switch_to_guest) | |||
152 | addl $8, %esp | 183 | addl $8, %esp |
153 | 184 | ||
154 | // The last five stack slots hold return address | 185 | // The last five stack slots hold return address |
155 | // And everything needed to change privilege | 186 | // And everything needed to switch privilege |
156 | // Into the Guest privilege level of 1, | 187 | // From Switcher's level 0 to Guest's 1, |
157 | // And the stack where the Guest had last left it. | 188 | // And the stack where the Guest had last left it. |
158 | // Interrupts are turned back on: we are Guest. | 189 | // Interrupts are turned back on: we are Guest. |
159 | iret | 190 | iret |
160 | 191 | ||
161 | // There are two paths where we switch to the Host | 192 | // We treat two paths to switch back to the Host |
193 | // Yet both must save Guest state and restore Host | ||
162 | // So we put the routine in a macro. | 194 | // So we put the routine in a macro. |
163 | // We are on our way home, back to the Host | ||
164 | // Interrupted out of the Guest, we come here. | ||
165 | #define SWITCH_TO_HOST \ | 195 | #define SWITCH_TO_HOST \ |
166 | /* We save the Guest state: all registers first \ | 196 | /* We save the Guest state: all registers first \ |
167 | * Laid out just as "struct lguest_regs" defines */ \ | 197 | * Laid out just as "struct lguest_regs" defines */ \ |
@@ -194,7 +224,7 @@ ENTRY(switch_to_guest) | |||
194 | movl %esp, %eax; \ | 224 | movl %esp, %eax; \ |
195 | andl $(~(1 << PAGE_SHIFT - 1)), %eax; \ | 225 | andl $(~(1 << PAGE_SHIFT - 1)), %eax; \ |
196 | /* Save our trap number: the switch will obscure it \ | 226 | /* Save our trap number: the switch will obscure it \ |
197 | * (The Guest regs are not mapped here in the Host) \ | 227 | * (In the Host the Guest regs are not mapped here) \ |
198 | * %ebx holds it safe for deliver_to_host */ \ | 228 | * %ebx holds it safe for deliver_to_host */ \ |
199 | movl LGUEST_PAGES_regs_trapnum(%eax), %ebx; \ | 229 | movl LGUEST_PAGES_regs_trapnum(%eax), %ebx; \ |
200 | /* The Host GDT, IDT and stack! \ | 230 | /* The Host GDT, IDT and stack! \ |
@@ -210,9 +240,9 @@ ENTRY(switch_to_guest) | |||
210 | /* Switch to Host's GDT, IDT. */ \ | 240 | /* Switch to Host's GDT, IDT. */ \ |
211 | lgdt LGUEST_PAGES_host_gdt_desc(%eax); \ | 241 | lgdt LGUEST_PAGES_host_gdt_desc(%eax); \ |
212 | lidt LGUEST_PAGES_host_idt_desc(%eax); \ | 242 | lidt LGUEST_PAGES_host_idt_desc(%eax); \ |
213 | /* Restore the Host's stack where it's saved regs lie */ \ | 243 | /* Restore the Host's stack where its saved regs lie */ \ |
214 | movl LGUEST_PAGES_host_sp(%eax), %esp; \ | 244 | movl LGUEST_PAGES_host_sp(%eax), %esp; \ |
215 | /* Last the TSS: our Host is complete */ \ | 245 | /* Last the TSS: our Host is returned */ \ |
216 | movl $(GDT_ENTRY_TSS*8), %edx; \ | 246 | movl $(GDT_ENTRY_TSS*8), %edx; \ |
217 | ltr %dx; \ | 247 | ltr %dx; \ |
218 | /* Restore now the regs saved right at the first. */ \ | 248 | /* Restore now the regs saved right at the first. */ \ |
@@ -222,14 +252,15 @@ ENTRY(switch_to_guest) | |||
222 | popl %ds; \ | 252 | popl %ds; \ |
223 | popl %es | 253 | popl %es |
224 | 254 | ||
225 | // Here's where we come when the Guest has just trapped: | 255 | // The first path is trod when the Guest has trapped: |
226 | // (Which trap we'll see has been pushed on the stack). | 256 | // (Which trap it was has been pushed on the stack). |
227 | // We need only switch back, and the Host will decode | 257 | // We need only switch back, and the Host will decode |
228 | // Why we came home, and what needs to be done. | 258 | // Why we came home, and what needs to be done. |
229 | return_to_host: | 259 | return_to_host: |
230 | SWITCH_TO_HOST | 260 | SWITCH_TO_HOST |
231 | iret | 261 | iret |
232 | 262 | ||
263 | // We are lead to the second path like so: | ||
233 | // An interrupt, with some cause external | 264 | // An interrupt, with some cause external |
234 | // Has ajerked us rudely from the Guest's code | 265 | // Has ajerked us rudely from the Guest's code |
235 | // Again we must return home to the Host | 266 | // Again we must return home to the Host |
@@ -238,7 +269,7 @@ deliver_to_host: | |||
238 | // But now we must go home via that place | 269 | // But now we must go home via that place |
239 | // Where that interrupt was supposed to go | 270 | // Where that interrupt was supposed to go |
240 | // Had we not been ensconced, running the Guest. | 271 | // Had we not been ensconced, running the Guest. |
241 | // Here we see the cleverness of our stack: | 272 | // Here we see the trickness of run_guest_once(): |
242 | // The Host stack is formed like an interrupt | 273 | // The Host stack is formed like an interrupt |
243 | // With EIP, CS and EFLAGS layered. | 274 | // With EIP, CS and EFLAGS layered. |
244 | // Interrupt handlers end with "iret" | 275 | // Interrupt handlers end with "iret" |
@@ -263,7 +294,7 @@ deliver_to_host: | |||
263 | xorw %ax, %ax | 294 | xorw %ax, %ax |
264 | orl %eax, %edx | 295 | orl %eax, %edx |
265 | // Now the address of the handler's in %edx | 296 | // Now the address of the handler's in %edx |
266 | // We call it now: its "iret" takes us home. | 297 | // We call it now: its "iret" drops us home. |
267 | jmp *%edx | 298 | jmp *%edx |
268 | 299 | ||
269 | // Every interrupt can come to us here | 300 | // Every interrupt can come to us here |