1 #include <palacios/vmm.h>
2 #include <palacios/vmm_emulator.h>
3 #include <palacios/vm_guest_mem.h>
4 #include <palacios/vmm_decoder.h>
5 #include <palacios/vmm_debug.h>
6 #include <palacios/vmcb.h>
7 #include <palacios/vmm_ctrl_regs.h>
9 static const char VMMCALL[3] = {0x0f, 0x01, 0xd9};
11 #ifndef DEBUG_EMULATOR
13 #define PrintDebug(fmt, args...)
17 int init_emulator(struct guest_info * info) {
18 struct emulation_state * emulator = &(info->emulator);
20 emulator->num_emulated_pages = 0;
21 INIT_LIST_HEAD(&(emulator->emulated_pages));
24 emulator->num_saved_pages = 0;
25 INIT_LIST_HEAD(&(emulator->saved_pages));
27 emulator->num_write_regions = 0;
28 INIT_LIST_HEAD(&(emulator->write_regions));
30 emulator->running = 0;
31 emulator->instr_length = 0;
33 emulator->tf_enabled = 0;
38 static addr_t get_new_page() {
39 void * page = V3_AllocPages(1);
40 memset(page, 0, PAGE_SIZE);
46 static int setup_code_page(struct guest_info * info, char * instr, struct basic_instr_info * instr_info ) {
47 addr_t code_page_offset = PT32_PAGE_OFFSET(info->rip);
48 addr_t code_page = get_new_page();
49 struct emulated_page * new_code_page = V3_Malloc(sizeof(struct emulated_page));
50 struct saved_page * saved_code_page = V3_Malloc(sizeof(struct saved_page));
53 saved_code_page->va = PT32_PAGE_ADDR(info->rip);
55 new_code_page->page_addr = code_page;
56 new_code_page->va = PT32_PAGE_ADDR(info->rip);
58 new_code_page->pte.present = 1;
59 new_code_page->pte.writable = 0;
60 new_code_page->pte.user_page = 1;
61 new_code_page->pte.page_base_addr = PT32_BASE_ADDR(code_page);
63 memcpy((void *)(code_page + code_page_offset), instr, instr_info->instr_length);
64 memcpy((void *)(code_page + code_page_offset + instr_info->instr_length), VMMCALL, 3);
67 PrintDebug("New Instr Stream:\n");
68 PrintTraceMemDump((void *)(code_page + code_page_offset), 32);
69 PrintDebug("rip =%x\n", info->rip);
74 v3_replace_shdw_page32(info, new_code_page->va, &(new_code_page->pte), &(saved_code_page->pte));
77 list_add(&(new_code_page->page_list), &(info->emulator.emulated_pages));
78 info->emulator.num_emulated_pages++;
80 list_add(&(saved_code_page->page_list), &(info->emulator.saved_pages));
81 info->emulator.num_saved_pages++;
88 static int set_stepping(struct guest_info * info) {
89 vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
90 ctrl_area->exceptions.db = 1;
92 info->emulator.tf_enabled = ((struct rflags *)&(info->ctrl_regs.rflags))->tf;
94 ((struct rflags *)&(info->ctrl_regs.rflags))->tf = 1;
100 static int unset_stepping(struct guest_info * info) {
101 vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
102 ctrl_area->exceptions.db = 0;
104 ((struct rflags *)&(info->ctrl_regs.rflags))->tf = info->emulator.tf_enabled;
106 if (info->emulator.tf_enabled) {
107 // Inject breakpoint exception into guest
115 // get the current instr
116 // check if rep + remove
117 // put into new page, vmexit after
118 // replace new page with current eip page
120 int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva,
121 int (*read)(addr_t read_addr, void * dst, uint_t length, void * priv_data),
122 addr_t read_gpa, void * private_data) {
123 struct basic_instr_info instr_info;
126 struct emulated_page * data_page = V3_Malloc(sizeof(struct emulated_page));
127 addr_t data_addr_offset = PT32_PAGE_OFFSET(read_gva);
130 PrintDebug("Emulating Read\n");
132 if (info->mem_mode == PHYSICAL_MEM) {
133 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
135 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
138 #ifdef DEBUG_EMULATOR
139 PrintDebug("Instr (15 bytes) at %x:\n", instr);
140 PrintTraceMemDump(instr, 15);
144 if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
145 PrintError("Could not do a basic memory instruction decode\n");
151 if (instr_info.has_rep == 1) {
152 PrintError("We currently don't handle rep* instructions\n");
158 data_page->page_addr = get_new_page();
159 data_page->va = PT32_PAGE_ADDR(read_gva);
160 data_page->pte.present = 1;
161 data_page->pte.writable = 0;
162 data_page->pte.user_page = 1;
163 data_page->pte.page_base_addr = PT32_BASE_ADDR(data_page->page_addr);
166 // Read the data directly onto the emulated page
167 if (read(read_gpa, (void *)(data_page->page_addr + data_addr_offset), instr_info.op_size, private_data) != instr_info.op_size) {
168 PrintError("Read error in emulator\n");
169 V3_FreePage((void *)(data_page->page_addr));
174 v3_replace_shdw_page32(info, data_page->va, &(data_page->pte), &saved_pte);
177 list_add(&(data_page->page_list), &(info->emulator.emulated_pages));
178 info->emulator.num_emulated_pages++;
180 if (saved_pte.present == 1) {
181 struct saved_page * saved_data_page = V3_Malloc(sizeof(struct saved_page));
182 saved_data_page->pte = saved_pte;
183 saved_data_page->va = PT32_PAGE_ADDR(read_gva);
185 list_add(&(saved_data_page->page_list), &(info->emulator.saved_pages));
186 info->emulator.num_saved_pages++;
190 // setup_code_page(info, instr, &instr_info);
193 info->emulator.running = 1;
194 info->run_state = VM_EMULATING;
195 info->emulator.instr_length = instr_info.instr_length;
202 int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva,
203 int (*write)(addr_t write_addr, void * src, uint_t length, void * priv_data),
204 addr_t write_gpa, void * private_data) {
206 struct basic_instr_info instr_info;
209 struct write_region * write_op = V3_Malloc(sizeof(struct write_region ));
210 struct emulated_page * data_page = V3_Malloc(sizeof(struct emulated_page));
211 addr_t data_addr_offset = PT32_PAGE_OFFSET(write_gva);
215 PrintDebug("Emulating Write for instruction at 0x%x\n",info->rip);
217 if (info->mem_mode == PHYSICAL_MEM) {
218 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
220 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
224 PrintDebug("Instruction is");
225 for (i=0;i<15;i++) { PrintDebug(" 0x%x",instr[i]); }
228 if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
229 PrintError("Could not do a basic memory instruction decode\n");
235 if (instr_info.has_rep==1) {
236 PrintDebug("Emulated instruction has rep\n");
240 if (instr_info.has_rep == 1) {
241 PrintError("We currently don't handle rep* instructions\n");
248 data_page->page_addr = get_new_page();
249 data_page->va = PT32_PAGE_ADDR(write_gva);
250 data_page->pte.present = 1;
251 data_page->pte.writable = 1;
252 data_page->pte.user_page = 1;
253 data_page->pte.page_base_addr = PT32_BASE_ADDR(data_page->page_addr);
257 write_op->write = write;
258 write_op->write_addr = write_gpa;
259 write_op->length = instr_info.op_size;
260 write_op->private_data = private_data;
262 write_op->write_data = (void *)(data_page->page_addr + data_addr_offset);
264 list_add(&(write_op->write_list), &(info->emulator.write_regions));
265 info->emulator.num_write_regions--;
267 v3_replace_shdw_page32(info, data_page->va, &(data_page->pte), &saved_pte);
270 list_add(&(data_page->page_list), &(info->emulator.emulated_pages));
271 info->emulator.num_emulated_pages++;
273 if (saved_pte.present == 1) {
274 struct saved_page * saved_data_page = V3_Malloc(sizeof(struct saved_page));
275 saved_data_page->pte = saved_pte;
276 saved_data_page->va = PT32_PAGE_ADDR(write_gva);
278 list_add(&(saved_data_page->page_list), &(info->emulator.saved_pages));
279 info->emulator.num_saved_pages++;
283 if (info->emulator.running == 0) {
284 // setup_code_page(info, instr, &instr_info);
286 info->emulator.running = 1;
287 info->run_state = VM_EMULATING;
288 info->emulator.instr_length = instr_info.instr_length;
296 int v3_emulation_exit_handler(struct guest_info * info) {
297 struct saved_page * svpg, * p_svpg;
298 struct emulated_page * empg, * p_empg;
299 struct write_region * wr_reg, * p_wr_reg;
302 // Complete the writes
304 // swap out emulated pages with blank dummies
305 // swap in saved pages
308 PrintDebug("V3 Emulation Exit Handler\n");
310 list_for_each_entry_safe(wr_reg, p_wr_reg, &(info->emulator.write_regions), write_list) {
311 wr_reg->write(wr_reg->write_addr, wr_reg->write_data, wr_reg->length, wr_reg->private_data);
312 PrintDebug("Writing \n");
314 list_del(&(wr_reg->write_list));
318 info->emulator.num_write_regions = 0;
321 *(uint_t *)&dummy_pte = 0;
323 list_for_each_entry_safe(empg, p_empg, &(info->emulator.emulated_pages), page_list) {
326 PrintDebug("wiping page %x\n", empg->va);
328 v3_replace_shdw_page32(info, empg->va, &dummy_pte, &empte32_t);
329 V3_FreePage((void *)(empg->page_addr));
331 list_del(&(empg->page_list));
334 info->emulator.num_emulated_pages = 0;
336 list_for_each_entry_safe(svpg, p_svpg, &(info->emulator.saved_pages), page_list) {
338 PrintDebug("Setting Saved page %x back\n", svpg->va);
339 v3_replace_shdw_page32(info, empg->va, &(svpg->pte), &dummy_pte);
341 list_del(&(svpg->page_list));
344 info->emulator.num_saved_pages = 0;
346 info->run_state = VM_RUNNING;
347 info->emulator.running = 0;
348 //info->rip += info->emulator.instr_length;
351 PrintDebug("Returning to rip: 0x%x\n", info->rip);
353 info->emulator.instr_length = 0;
356 unset_stepping(info);
359 PrintDebug("returning from emulation\n");