aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-10-21 21:03:26 -0400
committerRusty Russell <rusty@rustcorp.com.au>2007-10-23 01:49:50 -0400
commit3c6b5bfa3cf3b4057788e08482a468cc3bc00780 (patch)
treef0d67890f6f8c9d0840c9b19a483ec06cbf822ef /drivers/lguest
parent6649bb7af6a819b675bfcf22ab704737e905645a (diff)
Introduce guest mem offset, static link example launcher
In order to avoid problematic special linking of the Launcher, we give the Host an offset: this means we can use any memory region in the Launcher as Guest memory rather than insisting on mmap() at 0. The result is quite pleasing: a number of casts are replaced with simple additions. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/lguest')
-rw-r--r--drivers/lguest/core.c22
-rw-r--r--drivers/lguest/hypercalls.c15
-rw-r--r--drivers/lguest/io.c18
-rw-r--r--drivers/lguest/lg.h3
-rw-r--r--drivers/lguest/lguest_user.c23
-rw-r--r--drivers/lguest/page_tables.c7
6 files changed, 50 insertions, 38 deletions
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index a0788c12b392..eb95860cf098 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -325,8 +325,8 @@ static int emulate_insn(struct lguest *lg)
325 * Dealing With Guest Memory. 325 * Dealing With Guest Memory.
326 * 326 *
327 * When the Guest gives us (what it thinks is) a physical address, we can use 327 * When the Guest gives us (what it thinks is) a physical address, we can use
328 * the normal copy_from_user() & copy_to_user() on that address: remember, 328 * the normal copy_from_user() & copy_to_user() on the corresponding place in
329 * Guest physical == Launcher virtual. 329 * the memory region allocated by the Launcher.
330 * 330 *
331 * But we can't trust the Guest: it might be trying to access the Launcher 331 * But we can't trust the Guest: it might be trying to access the Launcher
332 * code. We have to check that the range is below the pfn_limit the Launcher 332 * code. We have to check that the range is below the pfn_limit the Launcher
@@ -348,8 +348,8 @@ u32 lgread_u32(struct lguest *lg, unsigned long addr)
348 348
349 /* Don't let them access lguest binary. */ 349 /* Don't let them access lguest binary. */
350 if (!lguest_address_ok(lg, addr, sizeof(val)) 350 if (!lguest_address_ok(lg, addr, sizeof(val))
351 || get_user(val, (u32 __user *)addr) != 0) 351 || get_user(val, (u32 *)(lg->mem_base + addr)) != 0)
352 kill_guest(lg, "bad read address %#lx", addr); 352 kill_guest(lg, "bad read address %#lx: pfn_limit=%u membase=%p", addr, lg->pfn_limit, lg->mem_base);
353 return val; 353 return val;
354} 354}
355 355
@@ -357,7 +357,7 @@ u32 lgread_u32(struct lguest *lg, unsigned long addr)
357void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val) 357void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
358{ 358{
359 if (!lguest_address_ok(lg, addr, sizeof(val)) 359 if (!lguest_address_ok(lg, addr, sizeof(val))
360 || put_user(val, (u32 __user *)addr) != 0) 360 || put_user(val, (u32 *)(lg->mem_base + addr)) != 0)
361 kill_guest(lg, "bad write address %#lx", addr); 361 kill_guest(lg, "bad write address %#lx", addr);
362} 362}
363 363
@@ -367,7 +367,7 @@ void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
367void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes) 367void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
368{ 368{
369 if (!lguest_address_ok(lg, addr, bytes) 369 if (!lguest_address_ok(lg, addr, bytes)
370 || copy_from_user(b, (void __user *)addr, bytes) != 0) { 370 || copy_from_user(b, lg->mem_base + addr, bytes) != 0) {
371 /* copy_from_user should do this, but as we rely on it... */ 371 /* copy_from_user should do this, but as we rely on it... */
372 memset(b, 0, bytes); 372 memset(b, 0, bytes);
373 kill_guest(lg, "bad read address %#lx len %u", addr, bytes); 373 kill_guest(lg, "bad read address %#lx len %u", addr, bytes);
@@ -379,7 +379,7 @@ void lgwrite(struct lguest *lg, unsigned long addr, const void *b,
379 unsigned bytes) 379 unsigned bytes)
380{ 380{
381 if (!lguest_address_ok(lg, addr, bytes) 381 if (!lguest_address_ok(lg, addr, bytes)
382 || copy_to_user((void __user *)addr, b, bytes) != 0) 382 || copy_to_user(lg->mem_base + addr, b, bytes) != 0)
383 kill_guest(lg, "bad write address %#lx len %u", addr, bytes); 383 kill_guest(lg, "bad write address %#lx len %u", addr, bytes);
384} 384}
385/* (end of memory access helper routines) :*/ 385/* (end of memory access helper routines) :*/
@@ -616,11 +616,9 @@ int run_guest(struct lguest *lg, unsigned long __user *user)
616 * 616 *
617 * Note that if the Guest were really messed up, this 617 * Note that if the Guest were really messed up, this
618 * could happen before it's done the INITIALIZE 618 * could happen before it's done the INITIALIZE
619 * hypercall, so lg->lguest_data will be NULL, so 619 * hypercall, so lg->lguest_data will be NULL */
620 * &lg->lguest_data->cr2 will be address 8. Writing 620 if (lg->lguest_data
621 * into that address won't hurt the Host at all, 621 && put_user(cr2, &lg->lguest_data->cr2))
622 * though. */
623 if (put_user(cr2, &lg->lguest_data->cr2))
624 kill_guest(lg, "Writing cr2"); 622 kill_guest(lg, "Writing cr2");
625 break; 623 break;
626 case 7: /* We've intercepted a Device Not Available fault. */ 624 case 7: /* We've intercepted a Device Not Available fault. */
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index 5ecd60b54201..02e67b49ea4f 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -205,16 +205,19 @@ static void initialize(struct lguest *lg)
205 tsc_speed = 0; 205 tsc_speed = 0;
206 206
207 /* The pointer to the Guest's "struct lguest_data" is the only 207 /* The pointer to the Guest's "struct lguest_data" is the only
208 * argument. */ 208 * argument. We check that address now. */
209 lg->lguest_data = (struct lguest_data __user *)lg->regs->edx;
210 /* If we check the address they gave is OK now, we can simply
211 * copy_to_user/from_user from now on rather than using lgread/lgwrite.
212 * I put this in to show that I'm not immune to writing stupid
213 * optimizations. */
214 if (!lguest_address_ok(lg, lg->regs->edx, sizeof(*lg->lguest_data))) { 209 if (!lguest_address_ok(lg, lg->regs->edx, sizeof(*lg->lguest_data))) {
215 kill_guest(lg, "bad guest page %p", lg->lguest_data); 210 kill_guest(lg, "bad guest page %p", lg->lguest_data);
216 return; 211 return;
217 } 212 }
213
214 /* Having checked it, we simply set lg->lguest_data to point straight
215 * into the Launcher's memory at the right place and then use
216 * copy_to_user/from_user from now on, instead of lgread/write. I put
217 * this in to show that I'm not immune to writing stupid
218 * optimizations. */
219 lg->lguest_data = lg->mem_base + lg->regs->edx;
220
218 /* The Guest tells us where we're not to deliver interrupts by putting 221 /* The Guest tells us where we're not to deliver interrupts by putting
219 * the range of addresses into "struct lguest_data". */ 222 * the range of addresses into "struct lguest_data". */
220 if (get_user(lg->noirq_start, &lg->lguest_data->noirq_start) 223 if (get_user(lg->noirq_start, &lg->lguest_data->noirq_start)
diff --git a/drivers/lguest/io.c b/drivers/lguest/io.c
index ea68613b43f6..3a845335fee8 100644
--- a/drivers/lguest/io.c
+++ b/drivers/lguest/io.c
@@ -186,7 +186,7 @@ int bind_dma(struct lguest *lg,
186 * we're doing this. */ 186 * we're doing this. */
187 mutex_lock(&lguest_lock); 187 mutex_lock(&lguest_lock);
188 down_read(fshared); 188 down_read(fshared);
189 if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) { 189 if (get_futex_key(lg->mem_base + ukey, fshared, &key) != 0) {
190 kill_guest(lg, "bad dma key %#lx", ukey); 190 kill_guest(lg, "bad dma key %#lx", ukey);
191 goto unlock; 191 goto unlock;
192 } 192 }
@@ -247,7 +247,8 @@ static int lgread_other(struct lguest *lg,
247 void *buf, u32 addr, unsigned bytes) 247 void *buf, u32 addr, unsigned bytes)
248{ 248{
249 if (!lguest_address_ok(lg, addr, bytes) 249 if (!lguest_address_ok(lg, addr, bytes)
250 || access_process_vm(lg->tsk, addr, buf, bytes, 0) != bytes) { 250 || access_process_vm(lg->tsk, (unsigned long)lg->mem_base + addr,
251 buf, bytes, 0) != bytes) {
251 memset(buf, 0, bytes); 252 memset(buf, 0, bytes);
252 kill_guest(lg, "bad address in registered DMA struct"); 253 kill_guest(lg, "bad address in registered DMA struct");
253 return 0; 254 return 0;
@@ -261,8 +262,8 @@ static int lgwrite_other(struct lguest *lg, u32 addr,
261 const void *buf, unsigned bytes) 262 const void *buf, unsigned bytes)
262{ 263{
263 if (!lguest_address_ok(lg, addr, bytes) 264 if (!lguest_address_ok(lg, addr, bytes)
264 || (access_process_vm(lg->tsk, addr, (void *)buf, bytes, 1) 265 || access_process_vm(lg->tsk, (unsigned long)lg->mem_base + addr,
265 != bytes)) { 266 (void *)buf, bytes, 1) != bytes) {
266 kill_guest(lg, "bad address writing to registered DMA"); 267 kill_guest(lg, "bad address writing to registered DMA");
267 return 0; 268 return 0;
268 } 269 }
@@ -318,7 +319,7 @@ static u32 copy_data(struct lguest *srclg,
318 * copy_to_user_page(), and some arch's seem to need special 319 * copy_to_user_page(), and some arch's seem to need special
319 * flushes. x86 is fine. */ 320 * flushes. x86 is fine. */
320 if (copy_from_user(maddr + (dst->addr[di] + dstoff)%PAGE_SIZE, 321 if (copy_from_user(maddr + (dst->addr[di] + dstoff)%PAGE_SIZE,
321 (void __user *)src->addr[si], len) != 0) { 322 srclg->mem_base+src->addr[si], len) != 0) {
322 /* If a copy failed, it's the source's fault. */ 323 /* If a copy failed, it's the source's fault. */
323 kill_guest(srclg, "bad address in sending DMA"); 324 kill_guest(srclg, "bad address in sending DMA");
324 totlen = 0; 325 totlen = 0;
@@ -377,7 +378,8 @@ static u32 do_dma(struct lguest *srclg, const struct lguest_dma *src,
377 * number of pages. Note that we're holding the destination's 378 * number of pages. Note that we're holding the destination's
378 * mmap_sem, as get_user_pages() requires. */ 379 * mmap_sem, as get_user_pages() requires. */
379 if (get_user_pages(dstlg->tsk, dstlg->mm, 380 if (get_user_pages(dstlg->tsk, dstlg->mm,
380 dst->addr[i], 1, 1, 1, pages+i, NULL) 381 (unsigned long)dstlg->mem_base+dst->addr[i],
382 1, 1, 1, pages+i, NULL)
381 != 1) { 383 != 1) {
382 /* This means the destination gave us a bogus buffer */ 384 /* This means the destination gave us a bogus buffer */
383 kill_guest(dstlg, "Error mapping DMA pages"); 385 kill_guest(dstlg, "Error mapping DMA pages");
@@ -493,7 +495,7 @@ again:
493 mutex_lock(&lguest_lock); 495 mutex_lock(&lguest_lock);
494 down_read(fshared); 496 down_read(fshared);
495 /* Get the futex key for the key the Guest gave us */ 497 /* Get the futex key for the key the Guest gave us */
496 if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) { 498 if (get_futex_key(lg->mem_base + ukey, fshared, &key) != 0) {
497 kill_guest(lg, "bad sending DMA key"); 499 kill_guest(lg, "bad sending DMA key");
498 goto unlock; 500 goto unlock;
499 } 501 }
@@ -584,7 +586,7 @@ unsigned long get_dma_buffer(struct lguest *lg,
584 586
585 /* This can fail if it's not a valid address, or if the address is not 587 /* This can fail if it's not a valid address, or if the address is not
586 * divisible by 4 (the futex code needs that, we don't really). */ 588 * divisible by 4 (the futex code needs that, we don't really). */
587 if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) { 589 if (get_futex_key(lg->mem_base + ukey, fshared, &key) != 0) {
588 kill_guest(lg, "bad registered DMA buffer"); 590 kill_guest(lg, "bad registered DMA buffer");
589 goto unlock; 591 goto unlock;
590 } 592 }
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 399eab852ab5..54f2c2472bec 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -142,6 +142,9 @@ struct lguest
142 struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */ 142 struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */
143 u16 guestid; 143 u16 guestid;
144 u32 pfn_limit; 144 u32 pfn_limit;
145 /* This provides the offset to the base of guest-physical
146 * memory in the Launcher. */
147 void __user *mem_base;
145 u32 page_offset; 148 u32 page_offset;
146 u32 cr2; 149 u32 cr2;
147 int halted; 150 int halted;
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 80d1b58c7698..816d4d12a801 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -1,9 +1,9 @@
1/*P:200 This contains all the /dev/lguest code, whereby the userspace launcher 1/*P:200 This contains all the /dev/lguest code, whereby the userspace launcher
2 * controls and communicates with the Guest. For example, the first write will 2 * controls and communicates with the Guest. For example, the first write will
3 * tell us the memory size, pagetable, entry point and kernel address offset. 3 * tell us the Guest's memory layout, pagetable, entry point and kernel address
4 * A read will run the Guest until a signal is pending (-EINTR), or the Guest 4 * offset. A read will run the Guest until something happens, such as a signal
5 * does a DMA out to the Launcher. Writes are also used to get a DMA buffer 5 * or the Guest doing a DMA out to the Launcher. Writes are also used to get a
6 * registered by the Guest and to send the Guest an interrupt. :*/ 6 * DMA buffer registered by the Guest and to send the Guest an interrupt. :*/
7#include <linux/uaccess.h> 7#include <linux/uaccess.h>
8#include <linux/miscdevice.h> 8#include <linux/miscdevice.h>
9#include <linux/fs.h> 9#include <linux/fs.h>
@@ -142,9 +142,11 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
142 return run_guest(lg, (unsigned long __user *)user); 142 return run_guest(lg, (unsigned long __user *)user);
143} 143}
144 144
145/*L:020 The initialization write supplies 4 32-bit values (in addition to the 145/*L:020 The initialization write supplies 5 32-bit values (in addition to the
146 * 32-bit LHREQ_INITIALIZE value). These are: 146 * 32-bit LHREQ_INITIALIZE value). These are:
147 * 147 *
148 * base: The start of the Guest-physical memory inside the Launcher memory.
149 *
148 * pfnlimit: The highest (Guest-physical) page number the Guest should be 150 * pfnlimit: The highest (Guest-physical) page number the Guest should be
149 * allowed to access. The Launcher has to live in Guest memory, so it sets 151 * allowed to access. The Launcher has to live in Guest memory, so it sets
150 * this to ensure the Guest can't reach it. 152 * this to ensure the Guest can't reach it.
@@ -166,7 +168,7 @@ static int initialize(struct file *file, const u32 __user *input)
166 * Guest. */ 168 * Guest. */
167 struct lguest *lg; 169 struct lguest *lg;
168 int err, i; 170 int err, i;
169 u32 args[4]; 171 u32 args[5];
170 172
171 /* We grab the Big Lguest lock, which protects the global array 173 /* We grab the Big Lguest lock, which protects the global array
172 * "lguests" and multiple simultaneous initializations. */ 174 * "lguests" and multiple simultaneous initializations. */
@@ -194,8 +196,9 @@ static int initialize(struct file *file, const u32 __user *input)
194 196
195 /* Populate the easy fields of our "struct lguest" */ 197 /* Populate the easy fields of our "struct lguest" */
196 lg->guestid = i; 198 lg->guestid = i;
197 lg->pfn_limit = args[0]; 199 lg->mem_base = (void __user *)(long)args[0];
198 lg->page_offset = args[3]; 200 lg->pfn_limit = args[1];
201 lg->page_offset = args[4];
199 202
200 /* We need a complete page for the Guest registers: they are accessible 203 /* We need a complete page for the Guest registers: they are accessible
201 * to the Guest and we can only grant it access to whole pages. */ 204 * to the Guest and we can only grant it access to whole pages. */
@@ -210,13 +213,13 @@ static int initialize(struct file *file, const u32 __user *input)
210 /* Initialize the Guest's shadow page tables, using the toplevel 213 /* Initialize the Guest's shadow page tables, using the toplevel
211 * address the Launcher gave us. This allocates memory, so can 214 * address the Launcher gave us. This allocates memory, so can
212 * fail. */ 215 * fail. */
213 err = init_guest_pagetable(lg, args[1]); 216 err = init_guest_pagetable(lg, args[2]);
214 if (err) 217 if (err)
215 goto free_regs; 218 goto free_regs;
216 219
217 /* Now we initialize the Guest's registers, handing it the start 220 /* Now we initialize the Guest's registers, handing it the start
218 * address. */ 221 * address. */
219 setup_regs(lg->regs, args[2]); 222 setup_regs(lg->regs, args[3]);
220 223
221 /* There are a couple of GDT entries the Guest expects when first 224 /* There are a couple of GDT entries the Guest expects when first
222 * booting. */ 225 * booting. */
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index b7a924ace684..9cd2faceb87c 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -152,7 +152,7 @@ static unsigned long get_pfn(unsigned long virtpfn, int write)
152static spte_t gpte_to_spte(struct lguest *lg, gpte_t gpte, int write) 152static spte_t gpte_to_spte(struct lguest *lg, gpte_t gpte, int write)
153{ 153{
154 spte_t spte; 154 spte_t spte;
155 unsigned long pfn; 155 unsigned long pfn, base;
156 156
157 /* The Guest sets the global flag, because it thinks that it is using 157 /* The Guest sets the global flag, because it thinks that it is using
158 * PGE. We only told it to use PGE so it would tell us whether it was 158 * PGE. We only told it to use PGE so it would tell us whether it was
@@ -160,11 +160,14 @@ static spte_t gpte_to_spte(struct lguest *lg, gpte_t gpte, int write)
160 * use the global bit, so throw it away. */ 160 * use the global bit, so throw it away. */
161 spte.flags = (gpte.flags & ~_PAGE_GLOBAL); 161 spte.flags = (gpte.flags & ~_PAGE_GLOBAL);
162 162
163 /* The Guest's pages are offset inside the Launcher. */
164 base = (unsigned long)lg->mem_base / PAGE_SIZE;
165
163 /* We need a temporary "unsigned long" variable to hold the answer from 166 /* We need a temporary "unsigned long" variable to hold the answer from
164 * get_pfn(), because it returns 0xFFFFFFFF on failure, which wouldn't 167 * get_pfn(), because it returns 0xFFFFFFFF on failure, which wouldn't
165 * fit in spte.pfn. get_pfn() finds the real physical number of the 168 * fit in spte.pfn. get_pfn() finds the real physical number of the
166 * page, given the virtual number. */ 169 * page, given the virtual number. */
167 pfn = get_pfn(gpte.pfn, write); 170 pfn = get_pfn(base + gpte.pfn, write);
168 if (pfn == -1UL) { 171 if (pfn == -1UL) {
169 kill_guest(lg, "failed to get page %u", gpte.pfn); 172 kill_guest(lg, "failed to get page %u", gpte.pfn);
170 /* When we destroy the Guest, we'll go through the shadow page 173 /* When we destroy the Guest, we'll go through the shadow page