Commit f938d2c892db0d80d144253d4a7b7083efdbedeb

Authored by Rusty Russell
Committed by Linus Torvalds
1 parent dfb68689bf

lguest: documentation I: Preparation

The netfilter code had very good documentation: the Netfilter Hacking HOWTO.
Noone ever read it.

So this time I'm trying something different, using a bit of Knuthiness.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 14 changed files with 218 additions and 19 deletions Side-by-side Diff

Documentation/lguest/extract
  1 +#! /bin/sh
  2 +
  3 +set -e
  4 +
  5 +PREFIX=$1
  6 +shift
  7 +
  8 +trap 'rm -r $TMPDIR' 0
  9 +TMPDIR=`mktemp -d`
  10 +
  11 +exec 3>/dev/null
  12 +for f; do
  13 + while IFS="
  14 +" read -r LINE; do
  15 + case "$LINE" in
  16 + *$PREFIX:[0-9]*:\**)
  17 + NUM=`echo "$LINE" | sed "s/.*$PREFIX:\([0-9]*\).*/\1/"`
  18 + if [ -f $TMPDIR/$NUM ]; then
  19 + echo "$TMPDIR/$NUM already exits prior to $f"
  20 + exit 1
  21 + fi
  22 + exec 3>>$TMPDIR/$NUM
  23 + echo $f | sed 's,\.\./,,g' > $TMPDIR/.$NUM
  24 + /bin/echo "$LINE" | sed -e "s/$PREFIX:[0-9]*//" -e "s/:\*/*/" >&3
  25 + ;;
  26 + *$PREFIX:[0-9]*)
  27 + NUM=`echo "$LINE" | sed "s/.*$PREFIX:\([0-9]*\).*/\1/"`
  28 + if [ -f $TMPDIR/$NUM ]; then
  29 + echo "$TMPDIR/$NUM already exits prior to $f"
  30 + exit 1
  31 + fi
  32 + exec 3>>$TMPDIR/$NUM
  33 + echo $f | sed 's,\.\./,,g' > $TMPDIR/.$NUM
  34 + /bin/echo "$LINE" | sed "s/$PREFIX:[0-9]*//" >&3
  35 + ;;
  36 + *:\**)
  37 + /bin/echo "$LINE" | sed -e "s/:\*/*/" -e "s,/\*\*/,," >&3
  38 + echo >&3
  39 + exec 3>/dev/null
  40 + ;;
  41 + *)
  42 + /bin/echo "$LINE" >&3
  43 + ;;
  44 + esac
  45 + done < $f
  46 + echo >&3
  47 + exec 3>/dev/null
  48 +done
  49 +
  50 +LASTFILE=""
  51 +for f in $TMPDIR/*; do
  52 + if [ "$LASTFILE" != $(cat $TMPDIR/.$(basename $f) ) ]; then
  53 + LASTFILE=$(cat $TMPDIR/.$(basename $f) )
  54 + echo "[ $LASTFILE ]"
  55 + fi
  56 + cat $f
  57 +done
Documentation/lguest/lguest.c
1   -/* Simple program to layout "physical" memory for new lguest guest.
2   - * Linked high to avoid likely physical memory. */
  1 +/*P:100 This is the Launcher code, a simple program which lays out the
  2 + * "physical" memory for the new Guest by mapping the kernel image and the
  3 + * virtual devices, then reads repeatedly from /dev/lguest to run the Guest.
  4 + *
  5 + * The only trick: the Makefile links it at a high address so it will be clear
  6 + * of the guest memory region. It means that each Guest cannot have more than
  7 + * about 2.5G of memory on a normally configured Host. :*/
3 8 #define _LARGEFILE64_SOURCE
4 9 #define _GNU_SOURCE
5 10 #include <stdio.h>
drivers/lguest/Makefile
... ... @@ -5,4 +5,16 @@
5 5 obj-$(CONFIG_LGUEST) += lg.o
6 6 lg-y := core.o hypercalls.o page_tables.o interrupts_and_traps.o \
7 7 segments.o io.o lguest_user.o switcher.o
  8 +
  9 +Preparation Preparation!: PREFIX=P
  10 +Guest: PREFIX=G
  11 +Drivers: PREFIX=D
  12 +Launcher: PREFIX=L
  13 +Host: PREFIX=H
  14 +Switcher: PREFIX=S
  15 +Mastery: PREFIX=M
  16 +Beer:
  17 + @for f in Preparation Guest Drivers Launcher Host Switcher Mastery; do echo "{==- $$f -==}"; make -s $$f; done; echo "{==-==}"
  18 +Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery:
  19 + @sh ../../Documentation/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'`
drivers/lguest/README
  1 +Welcome, friend reader, to lguest.
  2 +
  3 +Lguest is an adventure, with you, the reader, as Hero. I can't think of many
  4 +5000-line projects which offer both such capability and glimpses of future
  5 +potential; it is an exciting time to be delving into the source!
  6 +
  7 +But be warned; this is an arduous journey of several hours or more! And as we
  8 +know, all true Heroes are driven by a Noble Goal. Thus I offer a Beer (or
  9 +equivalent) to anyone I meet who has completed this documentation.
  10 +
  11 +So get comfortable and keep your wits about you (both quick and humorous).
  12 +Along your way to the Noble Goal, you will also gain masterly insight into
  13 +lguest, and hypervisors and x86 virtualization in general.
  14 +
  15 +Our Quest is in seven parts: (best read with C highlighting turned on)
  16 +
  17 +I) Preparation
  18 + - In which our potential hero is flown quickly over the landscape for a
  19 + taste of its scope. Suitable for the armchair coders and other such
  20 + persons of faint constitution.
  21 +
  22 +II) Guest
  23 + - Where we encounter the first tantalising wisps of code, and come to
  24 + understand the details of the life of a Guest kernel.
  25 +
  26 +III) Drivers
  27 + - Whereby the Guest finds its voice and become useful, and our
  28 + understanding of the Guest is completed.
  29 +
  30 +IV) Launcher
  31 + - Where we trace back to the creation of the Guest, and thus begin our
  32 + understanding of the Host.
  33 +
  34 +V) Host
  35 + - Where we master the Host code, through a long and tortuous journey.
  36 + Indeed, it is here that our hero is tested in the Bit of Despair.
  37 +
  38 +VI) Switcher
  39 + - Where our understanding of the intertwined nature of Guests and Hosts
  40 + is completed.
  41 +
  42 +VII) Mastery
  43 + - Where our fully fledged hero grapples with the Great Question:
  44 + "What next?"
  45 +
  46 +make Preparation!
  47 +Rusty Russell.
drivers/lguest/core.c
1   -/* World's simplest hypervisor, to test paravirt_ops and show
2   - * unbelievers that virtualization is the future. Plus, it's fun! */
  1 +/*P:400 This contains run_guest() which actually calls into the Host<->Guest
  2 + * Switcher and analyzes the return, such as determining if the Guest wants the
  3 + * Host to do something. This file also contains useful helper routines, and a
  4 + * couple of non-obvious setup and teardown pieces which were implemented after
  5 + * days of debugging pain. :*/
3 6 #include <linux/module.h>
4 7 #include <linux/stringify.h>
5 8 #include <linux/stddef.h>
drivers/lguest/hypercalls.c
1   -/* Actual hypercalls, which allow guests to actually do something.
2   - Copyright (C) 2006 Rusty Russell IBM Corporation
  1 +/*P:500 Just as userspace programs request kernel operations through a system
  2 + * call, the Guest requests Host operations through a "hypercall". You might
  3 + * notice this nomenclature doesn't really follow any logic, but the name has
  4 + * been around for long enough that we're stuck with it. As you'd expect, this
  5 + * code is basically a one big switch statement. :*/
  6 +
  7 +/* Copyright (C) 2006 Rusty Russell IBM Corporation
3 8  
4 9 This program is free software; you can redistribute it and/or modify
5 10 it under the terms of the GNU General Public License as published by
drivers/lguest/interrupts_and_traps.c
  1 +/*P:800 Interrupts (traps) are complicated enough to earn their own file.
  2 + * There are three classes of interrupts:
  3 + *
  4 + * 1) Real hardware interrupts which occur while we're running the Guest,
  5 + * 2) Interrupts for virtual devices attached to the Guest, and
  6 + * 3) Traps and faults from the Guest.
  7 + *
  8 + * Real hardware interrupts must be delivered to the Host, not the Guest.
  9 + * Virtual interrupts must be delivered to the Guest, but we make them look
  10 + * just like real hardware would deliver them. Traps from the Guest can be set
  11 + * up to go directly back into the Guest, but sometimes the Host wants to see
  12 + * them first, so we also have a way of "reflecting" them into the Guest as if
  13 + * they had been delivered to it directly. :*/
1 14 #include <linux/uaccess.h>
2 15 #include "lg.h"
3 16  
1   -/* Simple I/O model for guests, based on shared memory.
2   - * Copyright (C) 2006 Rusty Russell IBM Corporation
  1 +/*P:300 The I/O mechanism in lguest is simple yet flexible, allowing the Guest
  2 + * to talk to the Launcher or directly to another Guest. It uses familiar
  3 + * concepts of DMA and interrupts, plus some neat code stolen from
  4 + * futexes... :*/
  5 +
  6 +/* Copyright (C) 2006 Rusty Russell IBM Corporation
3 7 *
4 8 * This program is free software; you can redistribute it and/or modify
5 9 * it under the terms of the GNU General Public License as published by
drivers/lguest/lguest.c
1   -/*
2   - * Lguest specific paravirt-ops implementation
  1 +/*P:010
  2 + * A hypervisor allows multiple Operating Systems to run on a single machine.
  3 + * To quote David Wheeler: "Any problem in computer science can be solved with
  4 + * another layer of indirection."
3 5 *
  6 + * We keep things simple in two ways. First, we start with a normal Linux
  7 + * kernel and insert a module (lg.ko) which allows us to run other Linux
  8 + * kernels the same way we'd run processes. We call the first kernel the Host,
  9 + * and the others the Guests. The program which sets up and configures Guests
  10 + * (such as the example in Documentation/lguest/lguest.c) is called the
  11 + * Launcher.
  12 + *
  13 + * Secondly, we only run specially modified Guests, not normal kernels. When
  14 + * you set CONFIG_LGUEST to 'y' or 'm', this automatically sets
  15 + * CONFIG_LGUEST_GUEST=y, which compiles this file into the kernel so it knows
  16 + * how to be a Guest. This means that you can use the same kernel you boot
  17 + * normally (ie. as a Host) as a Guest.
  18 + *
  19 + * These Guests know that they cannot do privileged operations, such as disable
  20 + * interrupts, and that they have to ask the Host to do such things explicitly.
  21 + * This file consists of all the replacements for such low-level native
  22 + * hardware operations: these special Guest versions call the Host.
  23 + *
  24 + * So how does the kernel know it's a Guest? The Guest starts at a special
  25 + * entry point marked with a magic string, which sets up a few things then
  26 + * calls here. We replace the native functions in "struct paravirt_ops"
  27 + * with our Guest versions, then boot like normal. :*/
  28 +
  29 +/*
4 30 * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation.
5 31 *
6 32 * This program is free software; you can redistribute it and/or modify
drivers/lguest/lguest_bus.c
  1 +/*P:050 Lguest guests use a very simple bus for devices. It's a simple array
  2 + * of device descriptors contained just above the top of normal memory. The
  3 + * lguest bus is 80% tedious boilerplate code. :*/
1 4 #include <linux/init.h>
2 5 #include <linux/bootmem.h>
3 6 #include <linux/lguest_bus.h>
drivers/lguest/lguest_user.c
1   -/* Userspace control of the guest, via /dev/lguest. */
  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
  3 + * tell us the memory size, pagetable, entry point and kernel address offset.
  4 + * A read will run the Guest until a signal is pending (-EINTR), or the Guest
  5 + * does a DMA out to the Launcher. Writes are also used to get a DMA buffer
  6 + * registered by the Guest and to send the Guest an interrupt. :*/
2 7 #include <linux/uaccess.h>
3 8 #include <linux/miscdevice.h>
4 9 #include <linux/fs.h>
drivers/lguest/page_tables.c
1   -/* Shadow page table operations.
2   - * Copyright (C) Rusty Russell IBM Corporation 2006.
  1 +/*P:700 The pagetable code, on the other hand, still shows the scars of
  2 + * previous encounters. It's functional, and as neat as it can be in the
  3 + * circumstances, but be wary, for these things are subtle and break easily.
  4 + * The Guest provides a virtual to physical mapping, but we can neither trust
  5 + * it nor use it: we verify and convert it here to point the hardware to the
  6 + * actual Guest pages when running the Guest. :*/
  7 +
  8 +/* Copyright (C) Rusty Russell IBM Corporation 2006.
3 9 * GPL v2 and any later version */
4 10 #include <linux/mm.h>
5 11 #include <linux/types.h>
drivers/lguest/segments.c
  1 +/*P:600 The x86 architecture has segments, which involve a table of descriptors
  2 + * which can be used to do funky things with virtual address interpretation.
  3 + * We originally used to use segments so the Guest couldn't alter the
  4 + * Guest<->Host Switcher, and then we had to trim Guest segments, and restore
  5 + * for userspace per-thread segments, but trim again for on userspace->kernel
  6 + * transitions... This nightmarish creation was contained within this file,
  7 + * where we knew not to tread without heavy armament and a change of underwear.
  8 + *
  9 + * In these modern times, the segment handling code consists of simple sanity
  10 + * checks, and the worst you'll experience reading this code is butterfly-rash
  11 + * from frolicking through its parklike serenity. :*/
1 12 #include "lg.h"
2 13  
3 14 static int desc_ok(const struct desc_struct *gdt)
drivers/lguest/switcher.S
1   -/* This code sits at 0xFFC00000 to do the low-level guest<->host switch.
  1 +/*P:900 This is the Switcher: code which sits at 0xFFC00000 to do the low-level
  2 + * Guest<->Host switch. It is as simple as it can be made, but it's naturally
  3 + * very specific to x86.
  4 + *
  5 + * You have now completed Preparation. If this has whet your appetite; if you
  6 + * are feeling invigorated and refreshed then the next, more challenging stage
  7 + * can be found in "make Guest". :*/
2 8  
3   - There is are two pages above us for this CPU (struct lguest_pages).
4   - The second page (struct lguest_ro_state) becomes read-only after the
5   - context switch. The first page (the stack for traps) remains writable,
6   - but while we're in here, the guest cannot be running.
7   -*/
8 9 #include <linux/linkage.h>
9 10 #include <asm/asm-offsets.h>
10 11 #include "lg.h"