lcd-domains-arch.h 12.5 KB
Newer Older
1 2
#ifndef _ASM_X86_LCD_DOMAINS_ARCH_H
#define _ASM_X86_LCD_DOMAINS_ARCH_H
3

4
#include <asm/vmx.h>
5
#include <linux/spinlock.h>
6
#include <lcd-domains/utcb.h>
7

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
/* ADDRESS SPACE TYPES ---------------------------------------- */

typedef struct { unsigned long gva } gva_t;
typedef struct { unsigned long hva } hva_t;
typedef struct { unsigned long gpa } gpa_t;
typedef struct { unsigned long hpa } hpa_t;

static inline gva_t __gva(unsigned long gva)
{
	return (gva_t){ gva };
}
static inline unsigned long gva_val(gva_t gva)
{
	return gva.gva;
}
static inline unsigned long * gva_ptr(gva_t * gva)
{
	return &(gva->gva);
}
static inline gva_t gva_add(gva_t gva, unsigned long off)
{
	return __gva(gva_val(gva) + off);
}
static inline hva_t __hva(unsigned long hva)
{
	return (hva_t){ hva };
}
static inline unsigned long hva_val(hva_t hva)
{
	return hva.hva;
}
static inline unsigned long * hva_ptr(hva_t * hva)
{
	return &(hva->hva);
}
static inline hva_t hva_add(hva_t hva, unsigned long off)
{
	return __hva(hva_val(hva) + off);
}
static inline gpa_t __gpa(unsigned long gpa)
{
	return (gpa_t){ gpa };
}
static inline unsigned long gpa_val(gpa_t gpa)
{
	return gpa.gpa;
}
static inline unsigned long * gpa_ptr(gpa_t * gpa)
{
	return &(gpa->gpa);
}
static inline gpa_t gpa_add(gpa_t gpa, unsigned long off)
{
	return __gpa(gpa_val(gpa) + off);
}
static inline hpa_t __hpa(unsigned long hpa)
{
	return (hpa_t){ hpa };
}
static inline unsigned long hpa_val(hpa_t hpa)
{
	return hpa.hpa;
}
static inline unsigned long * hpa_ptr(hpa_t * hpa)
{
	return &(hpa->hpa);
}
static inline hpa_t hpa_add(hpa_t hpa, unsigned long off)
{
	return __hpa(hpa_val(hpa) + off);
}
79 80 81 82
static inline hpa_t pa2hpa(unsigned long pa)
{
	return (hpa_t){ pa };
}
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
static inline hpa_t va2hpa(void *va)
{
	return (hpa_t){ __pa(va) };
}
static inline void * hpa2va(hpa_t hpa)
{
	return __va(hpa_val(hpa));
}
static inline hva_t hpa2hva(hpa_t hpa)
{
	return (hva_t){ (unsigned long)__va(hpa.hpa) };
}
static inline hpa_t hva2hpa(hva_t hva)
{
	return (hpa_t){ (unsigned long)__pa(hva2va(hva)) };
}
static inline void * hva2va(hva_t hva)
{
	return (void *)hva_val(hva);
}


/* LCD ARCH DATA STRUCTURES ---------------------------------------- */

107
struct lcd_arch_vmcs {
108 109 110 111 112
	u32 revision_id;
	u32 abort;
	char data[0];
};

113
#define LCD_ARCH_NUM_AUTOLOAD_MSRS 0
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
enum lcd_arch_reg {
	LCD_ARCH_REGS_RAX = 0,
	LCD_ARCH_REGS_RCX = 1,
	LCD_ARCH_REGS_RDX = 2,
	LCD_ARCH_REGS_RBX = 3,
	LCD_ARCH_REGS_RSP = 4,
	LCD_ARCH_REGS_RBP = 5,
	LCD_ARCH_REGS_RSI = 6,
	LCD_ARCH_REGS_RDI = 7,
	LCD_ARCH_REGS_R8 = 8,
	LCD_ARCH_REGS_R9 = 9,
	LCD_ARCH_REGS_R10 = 10,
	LCD_ARCH_REGS_R11 = 11,
	LCD_ARCH_REGS_R12 = 12,
	LCD_ARCH_REGS_R13 = 13,
	LCD_ARCH_REGS_R14 = 14,
	LCD_ARCH_REGS_R15 = 15,
	LCD_ARCH_REGS_RIP,
	LCD_ARCH_NUM_REGS
134 135
};

Charlie Jacobsen's avatar
Charlie Jacobsen committed
136 137
#define LCD_ARCH_EPT_WALK_LENGTH 4
#define LCD_ARCH_EPTP_WALK_SHIFT 3
138
#define LCD_ARCH_PTRS_PER_EPTE   (1 << 9)
Charlie Jacobsen's avatar
Charlie Jacobsen committed
139

140
struct lcd_arch_ept {
141
	spinlock_t lock;
142
	hpa_t root;
143 144
	unsigned long vmcs_ptr;
	bool access_dirty_enabled;
145 146
};

147
typedef unsigned long lcd_arch_epte_t;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
148

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
struct lcd_arch_tss {
	/*
	 * Intel SDM V3 7.7
	 *
	 * Base TSS before I/O bitmap, etc.
	 */
	struct x86_hw_tss base_tss;
	/*
	 * I/O bitmap must be at least 8 bits to contain
	 * required 8 bits that are set.
	 *
	 * Intel SDM V1 16.5.2
	 */
	u8 io_bitmap[1];
} __attribute__((packed));

165
struct lcd_arch {
166 167 168
	/*
	 * Public Data
	 */
169
	struct {
170 171
		gva_t gv_fault_addr;
		gpa_t gp_fault_addr;
172
	} run_info;
173 174 175 176

	/*
	 * Private Data
	 */
177 178
	int cpu;
	int launched;
179
	int vpid;
180
	struct lcd_arch_vmcs *vmcs;
181

182
	struct lcd_arch_ept ept;
183 184
	struct desc_struct  *gdt;
	struct lcd_arch_tss *tss;
185
	struct lcd_utcb *utcb;
186 187 188 189 190 191 192 193 194

	u8  fail;
	u64 exit_reason;
	u64 exit_qualification;
	u32 idt_vectoring_info;
	u32 exit_intr_info;
	u32 error_code;
	u32 vec_no;
	u64 host_rsp;
195
	u64 regs[LCD_ARCH_NUM_REGS];
196 197 198 199 200
	u64 cr2;
	int shutdown;
	int ret_code;

	struct msr_autoload {
201 202 203
#if LCD_ARCH_NUM_AUTOLOAD_MSRS > 0
		struct vmx_msr_entry guest[LCD_ARCH_NUM_AUTOLOAD_MSRS];
		struct vmx_msr_entry host[LCD_ARCH_NUM_AUTOLOAD_MSRS];
204 205 206 207
#else
		struct vmx_msr_entry *guest;
		struct vmx_msr_entry *host;
#endif
208 209 210
	} msr_autoload;
};

211 212 213 214
/**
 * Initializes the arch-dependent code for LCD (detects required
 * features, turns on VMX on *all* cpu's).
 */
215
int lcd_arch_init(void);
216 217 218 219 220 221
/**
 * Turns off VMX on *all* cpu's and tears down arch-dependent code.
 * 
 * Important: All LCDs should be destroyed before calling this
 * routine (otherwise, memory will leak).
 */
222
void lcd_arch_exit(void);
223 224 225 226
/**
 * Creates the arch-dependent part of an LCD, and initializes 
 * the settings and most register values.
 */
227
struct lcd_arch *lcd_arch_create(void);
228 229 230 231
/**
 * Tears down arch-dep part of LCD. (If LCD is launched on
 * some cpu, it will become inactive.)
 */
232
void lcd_arch_destroy(struct lcd_arch *vcpu);
233 234 235 236 237
/**
 * Runs the LCD on the calling cpu. (If the LCD is active on
 * a different cpu, it will become inactive there.) Kernel
 * preemption is disabled while the LCD is launched, but
 * external interrupts are not disabled and will be handled.
238 239 240
 *
 * Unless the caller does otherwise, kernel preemption is
 * enabled before returning.
241 242 243
 *
 * Returns status code (e.g., LCD_ARCH_STATUS_PAGE_FAULT)
 * so that caller knows why lcd exited and can respond.
244 245 246 247 248 249 250
 */
int lcd_arch_run(struct lcd_arch *vcpu);

/**
 * Status codes for running LCDs.
 */
enum lcd_arch_status {
251
	LCD_ARCH_STATUS_PAGE_FAULT = 0,
252 253 254
	LCD_ARCH_STATUS_EXT_INTR   = 1,
	LCD_ARCH_STATUS_EPT_FAULT  = 2,
	LCD_ARCH_STATUS_CR3_ACCESS = 3,
255
	LCD_ARCH_STATUS_SYSCALL    = 4,
256
};
257

Charlie Jacobsen's avatar
Charlie Jacobsen committed
258
/**
259
 * Lookup ept entry for guest physical address a.
Charlie Jacobsen's avatar
Charlie Jacobsen committed
260 261 262 263
 *
 * Set create = 1 to allocate ept page table data structures
 * along the path as needed.
 */
264
int lcd_arch_ept_walk(struct lcd_arch *vcpu, gpa_t a, int create,
Charlie Jacobsen's avatar
Charlie Jacobsen committed
265 266 267 268
		lcd_arch_epte_t **epte_out);
/**
 * Set the guest physical => host physical mapping in the ept entry.
 */
269
void lcd_arch_ept_set(lcd_arch_epte_t *epte, hpa_t a);
Charlie Jacobsen's avatar
Charlie Jacobsen committed
270 271 272
/**
 * Read the host physical address stored in epte.
 */
273
hpa_t lcd_arch_ept_hpa(lcd_arch_epte_t *epte);
274 275 276 277 278 279 280 281
/**
 * Clears guest physical => host physical mapping in the ept.
 *
 * (This is not going to free up potentially empty paging structures
 * higher up in the ept hierarchy; but, for now, unset is used when
 * we're tearing down the lcd -- due to an error -- so the paging
 * structures will be freed up when the ept is torn down.)
 */
282
int lcd_arch_ept_unset(lcd_arch_epte_t *epte);
283 284 285 286 287 288
/**
 * Simple routine combining ept walk and set.
 *
 * overwrite = 0  => do not overwrite if ept entry is already present
 * overwrite = 1  => overwrite any existing ept entry
 */
289 290
int lcd_arch_ept_map(struct lcd_arch *vcpu, gpa_t ga, hpa_t ha,
		int create, int overwrite);
291 292 293
/**
 * Maps 
 *
294
 *    ga_start --> ga_start + npages * PAGE_SIZE
295 296 297
 *
 * to
 *
298
 *    ha_start --> ha_start + npages * PAGE_SIZE
299 300 301
 *
 * in lcd's ept.
 */
302 303
int lcd_arch_ept_map_range(struct lcd_arch *lcd, gpa_t ga_start, 
			hpa_t ha_start, unsigned long npages);
304 305 306
/**
 * Simple routine combining ept walk and unset.
 */
307
int lcd_arch_ept_unmap(struct lcd_arch *vcpu, gpa_t a);
308 309 310
/**
 * Unmaps 
 *
311
 *    ga_start --> ga_start + npages * PAGE_SIZE
312 313 314
 *
 * in lcd's ept.
 */
315 316
int lcd_arch_ept_unmap_range(struct lcd_arch *lcd, gpa_t ga_start, 
			unsigned long npages);
317 318 319
/**
 * Simple routine combinding ept walk and get.
 */
320
int lcd_arch_ept_gpa_to_hpa(struct lcd_arch *vcpu, gpa_t ga, hpa_t *ha_out);
321 322
/**
 * Set the lcd's program counter to the guest physical address
323
 * a.
324
 */
325
int lcd_arch_set_pc(struct lcd_arch *vcpu, gpa_t a);
326 327
/**
 * Set the lcd's gva root pointer (for x86, %cr3) to the
328
 * guest physical address a.
329
 */
330
int lcd_arch_set_gva_root(struct lcd_arch *vcpu, gpa_t a);
Charlie Jacobsen's avatar
Charlie Jacobsen committed
331

332 333 334 335 336
/*
 * GDT Layout
 * ==========
 * 0 = NULL
 * 1 = Code segment
337 338
 * 2 = Data segment  (%fs, default not present)
 * 3 = Data segment  (%gs, default not present)
339 340 341 342 343 344
 * 4 = Task segment
 *
 * See Intel SDM V3 26.3.1.2, 26.3.1.3 for register requirements.
 * See Intel SDM V3 3.4.2, 3.4.3 for segment register layout
 * See Intel SDM V3 2.4.1 - 2.4.4 for gdtr, ldtr, idtr, tr
 */
345
#define LCD_ARCH_FS_BASE     __gpa(0UL);
346
#define LCD_ARCH_FS_LIMIT    0xFFFFFFFF
347
#define LCD_ARCH_GS_BASE     __gpa(0UL);
348
#define LCD_ARCH_GS_LIMIT    0xFFFFFFFF
349
#define LCD_ARCH_GDTR_BASE   __gpa(1UL << PAGE_SHIFT);
350
#define LCD_ARCH_GDTR_LIMIT  ((u32)~(PAGE_SIZE - 1))
351
#define LCD_ARCH_TSS_BASE    __gpa(2UL << PAGE_SHIFT);
352 353
/* tss base + limit = address of last byte in tss, hence -1 */
#define LCD_ARCH_TSS_LIMIT   (sizeof(struct lcd_arch_tss) - 1)
354
#define LCD_ARCH_IDTR_BASE   __gpa(0UL);
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
#define LCD_ARCH_IDTR_LIMIT  0x0 /* no idt right now */

#define LCD_ARCH_CS_SELECTOR   (1 << 3)
#define LCD_ARCH_FS_SELECTOR   (2 << 3)
#define LCD_ARCH_GS_SELECTOR   (3 << 3)
#define LCD_ARCH_TR_SELECTOR   (4 << 3) /* TI must be 0 */
#define LCD_ARCH_LDTR_SELECTOR (0 << 3) /* unusable */

/*
 * Guest Physical Memory Layout
 * ============================
 *
 *                         +---------------------------+ 0xFFFF FFFF FFFF FFFF
 *                         |                           |
 *                         :                           :
 *                         :      Free / Unmapped      :
 *                         :                           :
 *                         |                           |
 * LCD_ARCH_STACK_TOP,---> +---------------------------+ 0x0000 0000 0000 4000
 * LCD_ARCH_FREE           |                           |
 *                         |          Stack            |
 *                         :       (grows down)        : (4 KBs)
 *                         :                           :
 *                         |                           |
379 380
 *                         |   User Thread Ctrl Block  |
 * LCD_ARCH_UTCB---------> +---------------------------+ 0x0000 0000 0000 3000
381 382 383 384 385
 *                         |           TSS             |
 *                         |    only sizeof(tss) is    | (4 KBs)
 *                         |           used            |
 * LCD_ARCH_TSS_BASE-----> +---------------------------+ 0x0000 0000 0000 2000
 *                         |           GDT             | (4 KBs)
386
 * LCD_ARCH_GDTR_BASE----> +---------------------------+ 0x0000 0000 0000 1000
387 388 389 390
 *                         |         Reserved          |
 *                         |       (not mapped)        | (4 KBs)
 *                         +---------------------------+ 0x0000 0000 0000 0000
 */
391 392
#define LCD_ARCH_UTCB        __gpa(3UL << PAGE_SHIFT);
#define LCD_ARCH_STACK_TOP   __gpa(4UL << PAGE_SHIFT);
393
#define LCD_ARCH_FREE        LCD_ARCH_STACK_TOP
Charlie Jacobsen's avatar
Charlie Jacobsen committed
394

395 396 397 398 399
/*
 * Accessor Macro for syscalls
 * ===========================
 */
#define LCD_ARCH_GET_SYSCALL_NUM(vcpu) (vcpu->regs[LCD_ARCH_REGS_RAX])
400

401 402 403 404 405 406
/*
 * Accessor Macro for utcb
 * =======================
 */
#define LCD_ARCH_GET_UTCB(vcpu) (vcpu->utcb);

407 408 409 410 411 412 413 414
/*
 * Accessor Macros for IPC
 * =======================
 *
 * Based on x86 seL4 message register design.
 *
 * See seL4 manual, 4.1.
 */
415
#define LCD_ARCH_GET_CAP_REG(vcpu) (vcpu->regs[LCD_ARCH_REGS_RBX])
416 417 418
#define LCD_ARCH_GET_BDG_REG(vcpu) (vcpu->regs[LCD_ARCH_REGS_RBX])
#define LCD_ARCH_GET_TAG_REG(vcpu) (vcpu->regs[LCD_ARCH_REGS_RSI])
#define LCD_ARCH_GET_MSG_REG(vcpu, idx) (__lcd_arch_get_msg_reg(vcpu, idx))
419 420
static inline u64 __lcd_arch_get_msg_reg(struct lcd_arch *vcpu, 
					unsigned int idx)
421 422 423 424 425 426
{
	/*
	 * Message regs 0 and 1 are fast (use machine registers)
	 *
	 * Message regs 2, ... always use the mr's in struct lcd_ipc_regs.
	 *
427
	 * (The first two mr's in utcb are reserved for
428
	 * mr's 0 and 1. If the caller wishes to explicitly use those mr's,
429
	 * they should do so by manually accessing the mr's in utcb.)
430 431
	 */
	if (idx == 0)
432
		return vcpu->regs[LCD_ARCH_REGS_RDI];
433
	else if (idx == 1)
434
		return vcpu->regs[LCD_ARCH_REGS_RBP];
435
	else
436
		return vcpu->utcb->ipc.mr[idx];
437 438 439
}

#define LCD_ARCH_SET_CAP_REG(vcpu, val) ({                    \
440
			vcpu->regs[LCD_ARCH_REGS_RBX] = val;  \
441 442 443 444 445 446 447 448 449 450
		})
#define LCD_ARCH_SET_BDG_REG(vcpu, val) ({                    \
			vcpu->regs[LCD_ARCH_REGS_RBX] = val;  \
		})
#define LCD_ARCH_SET_TAG_REG(vcpu, val) ({                    \
			vcpu->regs[LCD_ARCH_REGS_RSI] = val;  \
		})
#define LCD_ARCH_SET_MSG_REG(vcpu, idx, val) ({                 \
			__lcd_arch_set_msg_reg(vcpu, val, idx);	\
		})
451 452
static inline void __lcd_arch_set_msg_reg(struct lcd_arch *vcpu, 
					unsigned int idx, u64 val)
453 454 455 456 457 458
{
	/*
	 * Message regs 0 and 1 are fast (use machine registers)
	 *
	 * Message regs 2, ... always use the mr's in struct lcd_ipc_regs.
	 *
459
	 * (The first two mr's in utcb are reserved for
460
	 * mr's 0 and 1. If the caller wishes to explicitly use those mr's,
461
	 * they should do so by manually accessing the mr's in utcb.)
462 463
	 */
	if (idx == 0)
464
		vcpu->regs[LCD_ARCH_REGS_RDI] = val;
465
	else if (idx == 1)
466
		vcpu->regs[LCD_ARCH_REGS_RBP] = val;
467
	else
468
		vcpu->utcb->ipc.mr[idx] = val;
469 470
}

471
#endif  /* _ASM_X86_LCD_DOMAINS_ARCH_H */