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

#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <linux/init.h>
#include <linux/stringify.h>
#include <linux/lguest.h>
#include <linux/lguest_launcher.h>
#include <linux/wait.h>
11
#include <linux/hrtimer.h>
R
Rusty Russell 已提交
12 13
#include <linux/err.h>

14
#include <asm/lguest.h>
R
Rusty Russell 已提交
15 16 17 18

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

19
struct pgdir {
20
	unsigned long gpgdir;
21
	pgd_t *pgdir;
R
Rusty Russell 已提交
22 23 24
};

/* We have two pages shared with guests, per cpu.  */
25
struct lguest_pages {
R
Rusty Russell 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38
	/* 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

39 40 41
struct lg_cpu {
	unsigned int id;
	struct lguest *lg;
42 43
	struct task_struct *tsk;
	struct mm_struct *mm; 	/* == tsk->mm, but that becomes NULL on exit */
44

45 46 47
	u32 cr2;
	int ts;
	u32 esp1;
48
	u16 ss1;
49

50 51 52
	/* Bitmap of what has changed: see CHANGED_* above. */
	int changed;

53 54
	unsigned long pending_notify; /* pfn from LHCALL_NOTIFY */

R
Rusty Russell 已提交
55
	/* At end of a page shared mapped over lguest_pages in guest. */
56 57 58
	unsigned long regs_page;
	struct lguest_regs *regs;

59 60
	struct lguest_pages *last_pages;

R
Rusty Russell 已提交
61
	int cpu_pgd; /* Which pgd this cpu is currently using */
62

63 64 65
	/* If a hypercall was asked for, this points to the arguments. */
	struct hcall_args *hcall;
	u32 next_hcall;
66 67 68

	/* Virtual clock device */
	struct hrtimer hrt;
69

70
	/* Did the Guest tell us to halt? */
71 72
	int halted;

73 74
	/* Pending virtual interrupts */
	DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
75 76

	struct lg_cpu_arch arch;
77 78
};

79 80
struct lg_eventfd {
	unsigned long addr;
81
	struct eventfd_ctx *event;
82 83 84 85 86 87 88
};

struct lg_eventfd_map {
	unsigned int num;
	struct lg_eventfd map[];
};

R
Rusty Russell 已提交
89
/* The private info the thread maintains about the guest. */
90
struct lguest {
R
Rusty Russell 已提交
91
	struct lguest_data __user *lguest_data;
92 93 94
	struct lg_cpu cpus[NR_CPUS];
	unsigned int nr_cpus;

R
Rusty Russell 已提交
95
	u32 pfn_limit;
R
Rusty Russell 已提交
96 97 98 99 100

	/*
	 * This provides the offset to the base of guest-physical memory in the
	 * Launcher.
	 */
101
	void __user *mem_base;
102
	unsigned long kernel_address;
R
Rusty Russell 已提交
103 104 105 106 107 108 109 110

	struct pgdir pgdirs[4];

	unsigned long noirq_start, noirq_end;

	unsigned int stack_pages;
	u32 tsc_khz;

111 112
	struct lg_eventfd_map *eventfds;

R
Rusty Russell 已提交
113 114 115 116 117 118 119
	/* Dead? */
	const char *dead;
};

extern struct mutex lguest_lock;

/* core.c: */
120 121
bool lguest_address_ok(const struct lguest *lg,
		       unsigned long addr, unsigned long len);
122 123
void __lgread(struct lg_cpu *, void *, unsigned long, unsigned);
void __lgwrite(struct lg_cpu *, unsigned long, const void *, unsigned);
R
Rusty Russell 已提交
124

R
Rusty Russell 已提交
125 126
/*H:035
 * Using memory-copy operations like that is usually inconvient, so we
R
Rusty Russell 已提交
127 128 129
 * have the following helper macros which read and write a specific type (often
 * an unsigned long).
 *
R
Rusty Russell 已提交
130 131
 * This reads into a variable of the given type then returns that.
 */
132 133
#define lgread(cpu, addr, type)						\
	({ type _v; __lgread((cpu), &_v, (addr), sizeof(_v)); _v; })
R
Rusty Russell 已提交
134 135

/* This checks that the variable is of the given type, then writes it out. */
136
#define lgwrite(cpu, addr, type, val)				\
R
Rusty Russell 已提交
137 138
	do {							\
		typecheck(type, val);				\
139
		__lgwrite((cpu), (addr), &(val), sizeof(val));	\
R
Rusty Russell 已提交
140 141 142
	} while(0)
/* (end of memory access helper routines) :*/

143
int run_guest(struct lg_cpu *cpu, unsigned long __user *user);
R
Rusty Russell 已提交
144

R
Rusty Russell 已提交
145 146
/*
 * Helper macros to obtain the first 12 or the last 20 bits, this is only the
147
 * first step in the migration to the kernel types.  pte_pfn is already defined
R
Rusty Russell 已提交
148 149
 * in the kernel.
 */
150 151
#define pgd_flags(x)	(pgd_val(x) & ~PAGE_MASK)
#define pgd_pfn(x)	(pgd_val(x) >> PAGE_SHIFT)
M
Matias Zabaljauregui 已提交
152 153
#define pmd_flags(x)    (pmd_val(x) & ~PAGE_MASK)
#define pmd_pfn(x)	(pmd_val(x) >> PAGE_SHIFT)
R
Rusty Russell 已提交
154 155

/* interrupts_and_traps.c: */
156 157
unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more);
void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more);
158
void set_interrupt(struct lg_cpu *cpu, unsigned int irq);
159
bool deliver_trap(struct lg_cpu *cpu, unsigned int num);
160 161
void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i,
			  u32 low, u32 hi);
162 163
void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages);
void pin_stack_pages(struct lg_cpu *cpu);
R
Rusty Russell 已提交
164 165
void setup_default_idt_entries(struct lguest_ro_state *state,
			       const unsigned long *def);
166
void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
R
Rusty Russell 已提交
167
		const unsigned long *def);
168
void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta);
169
bool send_notify_to_eventfd(struct lg_cpu *cpu);
170
void init_clockdev(struct lg_cpu *cpu);
171 172 173
bool check_syscall_vector(struct lguest *lg);
int init_interrupts(void);
void free_interrupts(void);
R
Rusty Russell 已提交
174 175 176

/* segments.c: */
void setup_default_gdt_entries(struct lguest_ro_state *state);
177
void setup_guest_gdt(struct lg_cpu *cpu);
178 179
void load_guest_gdt_entry(struct lg_cpu *cpu, unsigned int i,
			  u32 low, u32 hi);
180 181 182
void guest_load_tls(struct lg_cpu *cpu, unsigned long tls_array);
void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt);
void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt);
R
Rusty Russell 已提交
183 184

/* page_tables.c: */
185
int init_guest_pagetable(struct lguest *lg);
R
Rusty Russell 已提交
186
void free_guest_pagetable(struct lguest *lg);
187
void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable);
188
void guest_set_pgd(struct lguest *lg, unsigned long gpgdir, u32 i);
M
Matias Zabaljauregui 已提交
189 190 191
#ifdef CONFIG_X86_PAE
void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i);
#endif
192
void guest_pagetable_clear_all(struct lg_cpu *cpu);
193
void guest_pagetable_flush_user(struct lg_cpu *cpu);
194
void guest_set_pte(struct lg_cpu *cpu, unsigned long gpgdir,
195
		   unsigned long vaddr, pte_t val);
196
void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages);
197
bool demand_page(struct lg_cpu *cpu, unsigned long cr2, int errcode);
198 199
void pin_page(struct lg_cpu *cpu, unsigned long vaddr);
unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr);
200
void page_table_guest_data_init(struct lg_cpu *cpu);
R
Rusty Russell 已提交
201

202 203 204
/* <arch>/core.c: */
void lguest_arch_host_init(void);
void lguest_arch_host_fini(void);
205
void lguest_arch_run_guest(struct lg_cpu *cpu);
206 207 208
void lguest_arch_handle_trap(struct lg_cpu *cpu);
int lguest_arch_init_hypercalls(struct lg_cpu *cpu);
int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args);
209
void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start);
210 211 212 213

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

R
Rusty Russell 已提交
214 215 216 217 218
/* lguest_user.c: */
int lguest_device_init(void);
void lguest_device_remove(void);

/* hypercalls.c: */
219
void do_hypercalls(struct lg_cpu *cpu);
220
void write_timestamp(struct lg_cpu *cpu);
R
Rusty Russell 已提交
221

222 223 224 225
/*L:035
 * Let's step aside for the moment, to study one important routine that's used
 * widely in the Host code.
 *
R
Rusty Russell 已提交
226
 * There are many cases where the Guest can do something invalid, like pass crap
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
 * 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)".
 */
246
#define kill_guest(cpu, fmt...)					\
R
Rusty Russell 已提交
247
do {								\
248 249 250 251
	if (!(cpu)->lg->dead) {					\
		(cpu)->lg->dead = kasprintf(GFP_ATOMIC, fmt);	\
		if (!(cpu)->lg->dead)				\
			(cpu)->lg->dead = ERR_PTR(-ENOMEM);	\
R
Rusty Russell 已提交
252 253
	}							\
} while(0)
254
/* (End of aside) :*/
R
Rusty Russell 已提交
255 256 257

#endif	/* __ASSEMBLY__ */
#endif	/* _LGUEST_H */