lcd-domains-arch.h 9 KB
Newer Older
1 2
#ifndef LCD_DOMAINS_ARCH_H
#define LCD_DOMAINS_ARCH_H
3

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

8
struct lcd_arch_vmcs {
9 10 11 12 13
	u32 revision_id;
	u32 abort;
	char data[0];
};

14
int lcd_arch_autoload_msrs[] = {
15
	/* NONE */
16
};
17
#define LCD_ARCH_NUM_AUTOLOAD_MSRS 0
18

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
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
38 39
};

Charlie Jacobsen's avatar
Charlie Jacobsen committed
40 41
#define LCD_ARCH_EPT_WALK_LENGTH 4
#define LCD_ARCH_EPTP_WALK_SHIFT 3
42
#define LCD_ARCH_PTRS_PER_EPTE   (1 << 9)
Charlie Jacobsen's avatar
Charlie Jacobsen committed
43

44
struct lcd_arch_ept {
45 46 47 48
	spinlock_t lock;
	unsigned long root_hpa;
	unsigned long vmcs_ptr;
	bool access_dirty_enabled;
49 50
};

Charlie Jacobsen's avatar
Charlie Jacobsen committed
51 52
typedef epte_t lcd_arch_epte_t;

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
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));

69
struct lcd_arch {
70 71 72
	/*
	 * Public Data
	 */
73 74 75 76
	struct {
		u64 gva;
		u64 gpa;
	} run_info;
77 78 79 80

	/*
	 * Private Data
	 */
81 82
	int cpu;
	int launched;
83
	int vpid;
84
	struct lcd_arch_vmcs *vmcs;
85

86
	struct lcd_arch_ept ept;
87 88
	struct desc_struct  *gdt;
	struct lcd_arch_tss *tss;
89
	struct lcd_utcb *utcb;
90 91 92 93 94 95 96 97 98

	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;
99
	u64 regs[LCD_ARCH_NUM_REGS];
100 101 102 103 104
	u64 cr2;
	int shutdown;
	int ret_code;

	struct msr_autoload {
105 106 107
#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];
108 109 110 111
#else
		struct vmx_msr_entry *guest;
		struct vmx_msr_entry *host;
#endif
112 113 114
	} msr_autoload;
};

115 116 117 118
/**
 * Initializes the arch-dependent code for LCD (detects required
 * features, turns on VMX on *all* cpu's).
 */
119
int lcd_arch_init(void);
120 121 122 123 124 125
/**
 * 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).
 */
126
void lcd_arch_exit(void);
127 128 129 130
/**
 * Creates the arch-dependent part of an LCD, and initializes 
 * the settings and most register values.
 */
131
struct lcd_arch *lcd_arch_create(void);
132 133 134 135
/**
 * Tears down arch-dep part of LCD. (If LCD is launched on
 * some cpu, it will become inactive.)
 */
136
void lcd_arch_destroy(struct lcd_arch *vcpu);
137 138 139 140 141
/**
 * 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.
142 143 144
 *
 * Unless the caller does otherwise, kernel preemption is
 * enabled before returning.
145 146 147
 *
 * Returns status code (e.g., LCD_ARCH_STATUS_PAGE_FAULT)
 * so that caller knows why lcd exited and can respond.
148 149 150 151 152 153 154
 */
int lcd_arch_run(struct lcd_arch *vcpu);

/**
 * Status codes for running LCDs.
 */
enum lcd_arch_status {
155
	LCD_ARCH_STATUS_PAGE_FAULT = 0,
156 157 158
	LCD_ARCH_STATUS_EXT_INTR   = 1,
	LCD_ARCH_STATUS_EPT_FAULT  = 2,
	LCD_ARCH_STATUS_CR3_ACCESS = 3,
159
	LCD_ARCH_STATUS_IPC        = 4,
160
};
161

Charlie Jacobsen's avatar
Charlie Jacobsen committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
/**
 * Lookup ept entry for guest physical address gpa.
 *
 * Set create = 1 to allocate ept page table data structures
 * along the path as needed.
 */
int lcd_arch_ept_walk(struct lcd_arch *vcpu, u64 gpa, int create,
		lcd_arch_epte_t **epte_out);
/**
 * Set the guest physical => host physical mapping in the ept entry.
 */
int lcd_arch_ept_set(lcd_arch_epte_t *epte, u64 hpa);
/**
 * Read the host physical address stored in epte.
 */
u64 lcd_arch_ept_hpa(lcd_arch_epte_t *epte);
178 179 180 181 182 183 184 185
/**
 * 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
 */
int lcd_arch_ept_map_gpa_to_hpa(struct lcd_arch *vcpu, u64 gpa, u64 hpa,
				int create, int overwrite);
Charlie Jacobsen's avatar
Charlie Jacobsen committed
186

187 188 189 190 191
/*
 * GDT Layout
 * ==========
 * 0 = NULL
 * 1 = Code segment
192 193
 * 2 = Data segment  (%fs, default not present)
 * 3 = Data segment  (%gs, default not present)
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 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
 * 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
 */
#define LCD_ARCH_FS_BASE     0x0UL
#define LCD_ARCH_FS_LIMIT    0xFFFFFFFF
#define LCD_ARCH_GS_BASE     0x0UL
#define LCD_ARCH_GS_LIMIT    0xFFFFFFFF
#define LCD_ARCH_GDTR_BASE   0x0000000000002000UL
#define LCD_ARCH_GDTR_LIMIT  ~(PAGE_SIZE - 1)
#define LCD_ARCH_TSS_BASE    0x0000000000003000UL
/* tss base + limit = address of last byte in tss, hence -1 */
#define LCD_ARCH_TSS_LIMIT   (sizeof(struct lcd_arch_tss) - 1)
#define LCD_ARCH_IDTR_BASE   0x0UL
#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)
 *                         :                           :
 *                         |                           |
234 235
 *                         |   User Thread Ctrl Block  |
 * LCD_ARCH_UTCB---------> +---------------------------+ 0x0000 0000 0000 3000
236 237 238 239 240 241 242 243 244 245
 *                         |           TSS             |
 *                         |    only sizeof(tss) is    | (4 KBs)
 *                         |           used            |
 * LCD_ARCH_TSS_BASE-----> +---------------------------+ 0x0000 0000 0000 2000
 *                         |           GDT             | (4 KBs)
 * LCD_ARCH_GDT_BASE-----> +---------------------------+ 0x0000 0000 0000 1000
 *                         |         Reserved          |
 *                         |       (not mapped)        | (4 KBs)
 *                         +---------------------------+ 0x0000 0000 0000 0000
 */
246
#define LCD_ARCH_UTCB        0x0000000000003000UL
247 248
#define LCD_ARCH_STACK_TOP   0x0000000000004000UL
#define LCD_ARCH_FREE        LCD_ARCH_STACK_TOP
Charlie Jacobsen's avatar
Charlie Jacobsen committed
249

250 251 252 253 254
/*
 * Accessor Macro for syscalls
 * ===========================
 */
#define LCD_ARCH_GET_SYSCALL_NUM(vcpu) (vcpu->regs[LCD_ARCH_REGS_RAX])
255 256 257 258 259 260 261 262 263

/*
 * Accessor Macros for IPC
 * =======================
 *
 * Based on x86 seL4 message register design.
 *
 * See seL4 manual, 4.1.
 */
264
#define LCD_ARCH_GET_CAP_REG(vcpu) (vcpu->regs[LCD_ARCH_REGS_RBX])
265 266 267 268 269 270 271 272 273 274
#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))
static inline u64 __lcd_arch_get_msg_reg(lcd_arch *vcpu, unsigned int idx)
{
	/*
	 * Message regs 0 and 1 are fast (use machine registers)
	 *
	 * Message regs 2, ... always use the mr's in struct lcd_ipc_regs.
	 *
275
	 * (The first two mr's in utcb are reserved for
276
	 * mr's 0 and 1. If the caller wishes to explicitly use those mr's,
277
	 * they should do so by manually accessing the mr's in utcb.)
278 279 280 281 282 283
	 */
	if (idx == 0)
		return vcpu->regs[LCD_ARCH_REGS_EDI];
	else if (idx == 1)
		return vcpu->regs[LCD_ARCH_REGS_EBP];
	else
284
		return vcpu->utcb->ipc.mr[idx];
285 286 287
}

#define LCD_ARCH_SET_CAP_REG(vcpu, val) ({                    \
288
			vcpu->regs[LCD_ARCH_REGS_RBX] = val;  \
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
		})
#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);	\
		})
static inline void __lcd_arch_set_msg_reg(lcd_arch *vcpu, unsigned int idx,
					u64 val)
{
	/*
	 * Message regs 0 and 1 are fast (use machine registers)
	 *
	 * Message regs 2, ... always use the mr's in struct lcd_ipc_regs.
	 *
307
	 * (The first two mr's in utcb are reserved for
308
	 * mr's 0 and 1. If the caller wishes to explicitly use those mr's,
309
	 * they should do so by manually accessing the mr's in utcb.)
310 311 312 313 314 315
	 */
	if (idx == 0)
		vcpu->regs[LCD_ARCH_REGS_EDI] = val;
	else if (idx == 1)
		vcpu->regs[LCD_ARCH_REGS_EBP] = val;
	else
316
		vcpu->utcb->ipc.mr[idx] = val;
317 318
}

319
#endif  /* LCD_DOMAINS_ARCH_H */