Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dde79789 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds
Browse files

lguest: documentation IV: Launcher



Documentation: The Launcher

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e2c97843
Loading
Loading
Loading
Loading
+555 −44

File changed.

Preview size limit exceeded, changes collapsed.

+22 −2
Original line number Diff line number Diff line
@@ -208,24 +208,39 @@ static int emulate_insn(struct lguest *lg)
	return 1;
}

/*L:305
 * Dealing With Guest Memory.
 *
 * When the Guest gives us (what it thinks is) a physical address, we can use
 * the normal copy_from_user() & copy_to_user() on that address: remember,
 * Guest physical == Launcher virtual.
 *
 * But we can't trust the Guest: it might be trying to access the Launcher
 * code.  We have to check that the range is below the pfn_limit the Launcher
 * gave us.  We have to make sure that addr + len doesn't give us a false
 * positive by overflowing, too. */
int lguest_address_ok(const struct lguest *lg,
		      unsigned long addr, unsigned long len)
{
	return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr);
}

/* Just like get_user, but don't let guest access lguest binary. */
/* This is a convenient routine to get a 32-bit value from the Guest (a very
 * common operation).  Here we can see how useful the kill_lguest() routine we
 * met in the Launcher can be: we return a random value (0) instead of needing
 * to return an error. */
u32 lgread_u32(struct lguest *lg, unsigned long addr)
{
	u32 val = 0;

	/* Don't let them access lguest binary */
	/* Don't let them access lguest binary. */
	if (!lguest_address_ok(lg, addr, sizeof(val))
	    || get_user(val, (u32 __user *)addr) != 0)
		kill_guest(lg, "bad read address %#lx", addr);
	return val;
}

/* Same thing for writing a value. */
void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
{
	if (!lguest_address_ok(lg, addr, sizeof(val))
@@ -233,6 +248,9 @@ void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
		kill_guest(lg, "bad write address %#lx", addr);
}

/* This routine is more generic, and copies a range of Guest bytes into a
 * buffer.  If the copy_from_user() fails, we fill the buffer with zeroes, so
 * the caller doesn't end up using uninitialized kernel memory. */
void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
{
	if (!lguest_address_ok(lg, addr, bytes)
@@ -243,6 +261,7 @@ void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
	}
}

/* Similarly, our generic routine to copy into a range of Guest bytes. */
void lgwrite(struct lguest *lg, unsigned long addr, const void *b,
	     unsigned bytes)
{
@@ -250,6 +269,7 @@ void lgwrite(struct lguest *lg, unsigned long addr, const void *b,
	    || copy_to_user((void __user *)addr, b, bytes) != 0)
		kill_guest(lg, "bad write address %#lx len %u", addr, bytes);
}
/* (end of memory access helper routines) :*/

static void set_ts(void)
{
+230 −17

File changed.

Preview size limit exceeded, changes collapsed.

+25 −0
Original line number Diff line number Diff line
@@ -244,6 +244,30 @@ unsigned long get_dma_buffer(struct lguest *lg, unsigned long key,
/* hypercalls.c: */
void do_hypercalls(struct lguest *lg);

/*L:035
 * Let's step aside for the moment, to study one important routine that's used
 * widely in the Host code.
 *
 * There are many cases where the Guest does something invalid, like pass crap
 * to a hypercall.  Since only the Guest kernel can make hypercalls, it's quite
 * acceptable to simply terminate the Guest and give the Launcher a nicely
 * formatted reason.  It's also simpler for the Guest itself, which doesn't
 * need to check most hypercalls for "success"; if you're still running, it
 * succeeded.
 *
 * Once this is called, the Guest will never run again, so most Host code can
 * call this then continue as if nothing had happened.  This means many
 * functions don't have to explicitly return an error code, which keeps the
 * code simple.
 *
 * It also means that this can be called more than once: only the first one is
 * remembered.  The only trick is that we still need to kill the Guest even if
 * we can't allocate memory to store the reason.  Linux has a neat way of
 * packing error codes into invalid pointers, so we use that here.
 *
 * Like any macro which uses an "if", it is safely wrapped in a run-once "do {
 * } while(0)".
 */
#define kill_guest(lg, fmt...)					\
do {								\
	if (!(lg)->dead) {					\
@@ -252,6 +276,7 @@ do { \
			(lg)->dead = ERR_PTR(-ENOMEM);		\
	}							\
} while(0)
/* (End of aside) :*/

static inline unsigned long guest_pa(struct lguest *lg, unsigned long vaddr)
{
+150 −9

File changed.

Preview size limit exceeded, changes collapsed.