lg.h 7.5 KB
Newer Older
R
Rusty Russell 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#ifndef _LGUEST_H
#define _LGUEST_H

#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <linux/init.h>
#include <linux/stringify.h>
#include <linux/futex.h>
#include <linux/lguest.h>
#include <linux/lguest_launcher.h>
#include <linux/wait.h>
#include <linux/err.h>
#include <asm/semaphore.h>

15
#include <asm/lguest.h>
R
Rusty Russell 已提交
16 17 18 19 20 21 22 23 24

void free_pagetables(void);
int init_pagetables(struct page **switcher_page, unsigned int pages);

struct lguest_dma_info
{
	struct list_head list;
	union futex_key key;
	unsigned long dmas;
25
	struct lguest *owner;
R
Rusty Russell 已提交
26 27 28 29 30 31 32
	u16 next_dma;
	u16 num_dmas;
	u8 interrupt; 	/* 0 when not registered */
};

struct pgdir
{
33
	unsigned long gpgdir;
34
	pgd_t *pgdir;
R
Rusty Russell 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
};

/* We have two pages shared with guests, per cpu.  */
struct lguest_pages
{
	/* This is the stack page mapped rw in guest */
	char spare[PAGE_SIZE - sizeof(struct lguest_regs)];
	struct lguest_regs regs;

	/* This is the host state & guest descriptor page, ro in guest */
	struct lguest_ro_state state;
} __attribute__((aligned(PAGE_SIZE)));

#define CHANGED_IDT		1
#define CHANGED_GDT		2
#define CHANGED_GDT_TLS		4 /* Actually a subset of CHANGED_GDT */
#define CHANGED_ALL	        3

/* The private info the thread maintains about the guest. */
struct lguest
{
	/* At end of a page shared mapped over lguest_pages in guest.  */
	unsigned long regs_page;
	struct lguest_regs *regs;
	struct lguest_data __user *lguest_data;
	struct task_struct *tsk;
	struct mm_struct *mm; 	/* == tsk->mm, but that becomes NULL on exit */
	u32 pfn_limit;
63 64 65
	/* This provides the offset to the base of guest-physical
	 * memory in the Launcher. */
	void __user *mem_base;
R
Rusty Russell 已提交
66 67 68 69 70 71 72 73
	u32 page_offset;
	u32 cr2;
	int halted;
	int ts;
	u32 next_hcall;
	u32 esp1;
	u8 ss1;

74
	/* If a hypercall was asked for, this points to the arguments. */
J
Jes Sorensen 已提交
75
	struct hcall_args *hcall;
76

R
Rusty Russell 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
	/* Do we need to stop what we're doing and return to userspace? */
	int break_out;
	wait_queue_head_t break_wq;

	/* Bitmap of what has changed: see CHANGED_* above. */
	int changed;
	struct lguest_pages *last_pages;

	/* We keep a small number of these. */
	u32 pgdidx;
	struct pgdir pgdirs[4];

	/* Cached wakeup: we hold a reference to this task. */
	struct task_struct *wake;

	unsigned long noirq_start, noirq_end;
	int dma_is_pending;
	unsigned long pending_dma; /* struct lguest_dma */
	unsigned long pending_key; /* address they're sending to */

	unsigned int stack_pages;
	u32 tsc_khz;

	struct lguest_dma_info dma[LGUEST_MAX_DMA];

	/* Dead? */
	const char *dead;

105
	struct lguest_arch arch;
R
Rusty Russell 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

	/* Virtual clock device */
	struct hrtimer hrt;

	/* Pending virtual interrupts */
	DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
};

extern struct mutex lguest_lock;

/* core.c: */
u32 lgread_u32(struct lguest *lg, unsigned long addr);
void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val);
void lgread(struct lguest *lg, void *buf, unsigned long addr, unsigned len);
void lgwrite(struct lguest *lg, unsigned long, const void *buf, unsigned len);
int lguest_address_ok(const struct lguest *lg,
		      unsigned long addr, unsigned long len);
int run_guest(struct lguest *lg, unsigned long __user *user);

125 126 127 128 129 130
/* Helper macros to obtain the first 12 or the last 20 bits, this is only the
 * first step in the migration to the kernel types.  pte_pfn is already defined
 * in the kernel. */
#define pgd_flags(x)	(pgd_val(x) & ~PAGE_MASK)
#define pte_flags(x)	(pte_val(x) & ~PAGE_MASK)
#define pgd_pfn(x)	(pgd_val(x) >> PAGE_SHIFT)
R
Rusty Russell 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

/* interrupts_and_traps.c: */
void maybe_do_interrupt(struct lguest *lg);
int deliver_trap(struct lguest *lg, unsigned int num);
void load_guest_idt_entry(struct lguest *lg, unsigned int i, u32 low, u32 hi);
void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages);
void pin_stack_pages(struct lguest *lg);
void setup_default_idt_entries(struct lguest_ro_state *state,
			       const unsigned long *def);
void copy_traps(const struct lguest *lg, struct desc_struct *idt,
		const unsigned long *def);
void guest_set_clockevent(struct lguest *lg, unsigned long delta);
void init_clockdev(struct lguest *lg);

/* segments.c: */
void setup_default_gdt_entries(struct lguest_ro_state *state);
void setup_guest_gdt(struct lguest *lg);
void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num);
void guest_load_tls(struct lguest *lg, unsigned long tls_array);
void copy_gdt(const struct lguest *lg, struct desc_struct *gdt);
void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt);

/* page_tables.c: */
int init_guest_pagetable(struct lguest *lg, unsigned long pgtable);
void free_guest_pagetable(struct lguest *lg);
void guest_new_pagetable(struct lguest *lg, unsigned long pgtable);
157
void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i);
R
Rusty Russell 已提交
158 159
void guest_pagetable_clear_all(struct lguest *lg);
void guest_pagetable_flush_user(struct lguest *lg);
160
void guest_set_pte(struct lguest *lg, unsigned long gpgdir,
161
		   unsigned long vaddr, pte_t val);
R
Rusty Russell 已提交
162 163 164 165
void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages);
int demand_page(struct lguest *info, unsigned long cr2, int errcode);
void pin_page(struct lguest *lg, unsigned long vaddr);

166 167 168 169 170
/* <arch>/core.c: */
void lguest_arch_host_init(void);
void lguest_arch_host_fini(void);
void lguest_arch_run_guest(struct lguest *lg);
void lguest_arch_handle_trap(struct lguest *lg);
J
Jes Sorensen 已提交
171 172
int lguest_arch_init_hypercalls(struct lguest *lg);
int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args);
173
void lguest_arch_setup_regs(struct lguest *lg, unsigned long start);
174 175 176 177

/* <arch>/switcher.S: */
extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];

R
Rusty Russell 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
/* lguest_user.c: */
int lguest_device_init(void);
void lguest_device_remove(void);

/* io.c: */
void lguest_io_init(void);
int bind_dma(struct lguest *lg,
	     unsigned long key, unsigned long udma, u16 numdmas, u8 interrupt);
void send_dma(struct lguest *info, unsigned long key, unsigned long udma);
void release_all_dma(struct lguest *lg);
unsigned long get_dma_buffer(struct lguest *lg, unsigned long key,
			     unsigned long *interrupt);

/* hypercalls.c: */
void do_hypercalls(struct lguest *lg);
193
void write_timestamp(struct lguest *lg);
R
Rusty Russell 已提交
194

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
/*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)".
 */
R
Rusty Russell 已提交
219 220 221 222 223 224 225 226
#define kill_guest(lg, fmt...)					\
do {								\
	if (!(lg)->dead) {					\
		(lg)->dead = kasprintf(GFP_ATOMIC, fmt);	\
		if (!(lg)->dead)				\
			(lg)->dead = ERR_PTR(-ENOMEM);		\
	}							\
} while(0)
227
/* (End of aside) :*/
R
Rusty Russell 已提交
228 229 230 231 232 233 234

static inline unsigned long guest_pa(struct lguest *lg, unsigned long vaddr)
{
	return vaddr - lg->page_offset;
}
#endif	/* __ASSEMBLY__ */
#endif	/* _LGUEST_H */