1 /* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
2 /* (c) 2008, The V3VEE Project <http://www.v3vee.org> */
5 #include <palacios/vmm_mem.h>
6 #include <palacios/vmm.h>
7 #include <palacios/vmcb.h>
8 #include <palacios/vmm_decoder.h>
9 #include <palacios/vm_guest_mem.h>
10 #include <palacios/vmm_ctrl_regs.h>
14 /* Segmentation is a problem here...
16 * When we get a memory operand, presumably we use the default segment (which is?)
17 * unless an alternate segment was specfied in the prefix...
21 #ifndef DEBUG_CTRL_REGS
23 #define PrintDebug(fmt, args...)
27 // First Attempt = 494 lines
28 // current = 106 lines
29 int handle_cr0_write(struct guest_info * info) {
32 struct x86_instr dec_instr;
34 if (info->mem_mode == PHYSICAL_MEM) {
35 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
37 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
40 /* The IFetch will already have faulted in the necessary bytes for the full instruction
42 // I think we should inject a GPF into the guest
43 PrintError("Could not read instruction (ret=%d)\n", ret);
48 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
49 PrintError("Could not decode instruction\n");
54 if (opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
55 struct cr0_real *real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
56 struct cr0_real *new_cr0 = (struct cr0_real *)(dec_instr.src_operand.operand);
61 new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
63 PrintDebug("OperandVal = %x\n", new_cr0_val);
65 PrintDebug("Old CR0=%x\n", *real_cr0);
66 *(uchar_t*)real_cr0 &= 0xf0;
67 *(uchar_t*)real_cr0 |= new_cr0_val;
68 PrintDebug("New CR0=%x\n", *real_cr0);
71 if (info->shdw_pg_mode == SHADOW_PAGING) {
72 struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
74 PrintDebug(" Old Shadow CR0=%x\n", *shadow_cr0);
75 *(uchar_t*)shadow_cr0 &= 0xf0;
76 *(uchar_t*)shadow_cr0 |= new_cr0_val;
77 PrintDebug("New Shadow CR0=%x\n", *shadow_cr0);
79 } else if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
80 PrintDebug("MOV2CR0\n");
82 if (info->cpu_mode == LONG) {
86 struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
87 struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.src_operand.operand);
89 PrintDebug("OperandVal = %x, length=%d\n", *new_cr0, dec_instr.src_operand.size);
92 PrintDebug("Old CR0=%x\n", *real_cr0);
96 if (info->shdw_pg_mode == SHADOW_PAGING) {
97 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
99 PrintDebug("Old Shadow CR0=%x\n", *shadow_cr0);
103 *shadow_cr0 = *new_cr0;
106 if (get_mem_mode(info) == VIRTUAL_MEM) {
107 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
109 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
111 info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
115 PrintDebug("New Shadow CR0=%x\n",*shadow_cr0);
117 PrintDebug("New CR0=%x\n", *real_cr0);
120 } else if (opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
122 struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
126 if (info->shdw_pg_mode == SHADOW_PAGING) {
127 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
131 PrintError("Unhandled opcode in handle_cr0_write\n");
135 info->rip += dec_instr.instr_length;
141 // First attempt = 253 lines
142 // current = 51 lines
143 int handle_cr0_read(struct guest_info * info) {
146 struct x86_instr dec_instr;
148 if (info->mem_mode == PHYSICAL_MEM) {
149 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
151 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
154 /* The IFetch will already have faulted in the necessary bytes for the full instruction
156 // I think we should inject a GPF into the guest
157 PrintError("Could not read instruction (ret=%d)\n", ret);
162 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
163 PrintError("Could not decode instruction\n");
167 if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
168 struct cr0_32 * virt_cr0 = (struct cr0_32 *)(dec_instr.dst_operand.operand);
169 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
171 PrintDebug("MOVCR2\n");
172 PrintDebug("CR0 at 0x%x\n", real_cr0);
174 if (info->shdw_pg_mode == SHADOW_PAGING) {
175 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
177 *virt_cr0 = *real_cr0;
180 PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
181 PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
182 } else if (opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
183 struct cr0_real *real_cr0= (struct cr0_real*)&(info->ctrl_regs.cr0);
184 struct cr0_real *virt_cr0 = (struct cr0_real *)(dec_instr.dst_operand.operand);
185 char cr0_val = *(char*)real_cr0 & 0x0f;
187 PrintDebug("SMSW\n");
189 PrintDebug("CR0 at 0x%x\n", real_cr0);
191 *(char *)virt_cr0 &= 0xf0;
192 *(char *)virt_cr0 |= cr0_val;
195 PrintError("Unhandled opcode in handle_cr0_read\n");
199 info->rip += dec_instr.instr_length;
206 // First Attempt = 256 lines
207 // current = 65 lines
208 int handle_cr3_write(struct guest_info * info) {
211 struct x86_instr dec_instr;
213 if (info->mem_mode == PHYSICAL_MEM) {
214 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
216 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
219 /* The IFetch will already have faulted in the necessary bytes for the full instruction
221 // I think we should inject a GPF into the guest
222 PrintError("Could not read instruction (ret=%d)\n", ret);
227 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
228 PrintError("Could not decode instruction\n");
232 if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
234 PrintDebug("MOV2CR3\n");
236 PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
238 if (info->shdw_pg_mode == SHADOW_PAGING) {
239 struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
240 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
241 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
245 PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n",
246 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
249 cached = cache_page_tables32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
252 PrintError("CR3 Cache failed\n");
254 } else if (cached == 0) {
257 PrintDebug("New CR3 is different - flushing shadow page table\n");
259 delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
261 shadow_pt = create_new_shadow_pt32();
263 shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
265 PrintDebug("Reusing cached shadow Page table\n");
268 shadow_cr3->pwt = new_cr3->pwt;
269 shadow_cr3->pcd = new_cr3->pcd;
272 *guest_cr3 = *new_cr3;
274 PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n",
275 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
277 if (info->mem_mode == VIRTUAL_MEM) {
278 // If we aren't in paged mode then we have to preserve the identity mapped CR3
279 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
283 PrintError("Unhandled opcode in handle_cr3_write\n");
287 info->rip += dec_instr.instr_length;
294 // first attempt = 156 lines
295 // current = 36 lines
296 int handle_cr3_read(struct guest_info * info) {
299 struct x86_instr dec_instr;
301 if (info->mem_mode == PHYSICAL_MEM) {
302 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
304 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
307 /* The IFetch will already have faulted in the necessary bytes for the full instruction
309 // I think we should inject a GPF into the guest
310 PrintError("Could not read instruction (ret=%d)\n", ret);
315 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
316 PrintError("Could not decode instruction\n");
320 if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
321 PrintDebug("MOVCR32\n");
322 struct cr3_32 * virt_cr3 = (struct cr3_32 *)(dec_instr.dst_operand.operand);
324 PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
326 if (info->shdw_pg_mode == SHADOW_PAGING) {
327 *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
329 *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
332 PrintError("Unhandled opcode in handle_cr3_read\n");
336 info->rip += dec_instr.instr_length;