1 #include <palacios/vmm_mem.h>
2 #include <palacios/vmm.h>
3 #include <palacios/vmcb.h>
4 #include <palacios/vmm_decoder.h>
5 #include <palacios/vm_guest_mem.h>
6 #include <palacios/vmm_ctrl_regs.h>
10 /* Segmentation is a problem here...
12 * When we get a memory operand, presumably we use the default segment (which is?)
13 * unless an alternate segment was specfied in the prefix...
17 #ifndef DEBUG_CTRL_REGS
19 #define PrintDebug(fmt, args...)
23 // First Attempt = 494 lines
24 // current = 106 lines
25 int handle_cr0_write(struct guest_info * info) {
28 struct x86_instr dec_instr;
30 if (info->mem_mode == PHYSICAL_MEM) {
31 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
33 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
36 /* The IFetch will already have faulted in the necessary bytes for the full instruction
38 // I think we should inject a GPF into the guest
39 PrintError("Could not read instruction (ret=%d)\n", ret);
44 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
45 PrintError("Could not decode instruction\n");
50 if (opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
51 struct cr0_real *real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
52 struct cr0_real *new_cr0 = (struct cr0_real *)(dec_instr.src_operand.operand);
57 new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
59 PrintDebug("OperandVal = %x\n", new_cr0_val);
61 PrintDebug("Old CR0=%x\n", *real_cr0);
62 *(uchar_t*)real_cr0 &= 0xf0;
63 *(uchar_t*)real_cr0 |= new_cr0_val;
64 PrintDebug("New CR0=%x\n", *real_cr0);
67 if (info->shdw_pg_mode == SHADOW_PAGING) {
68 struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
70 PrintDebug(" Old Shadow CR0=%x\n", *shadow_cr0);
71 *(uchar_t*)shadow_cr0 &= 0xf0;
72 *(uchar_t*)shadow_cr0 |= new_cr0_val;
73 PrintDebug("New Shadow CR0=%x\n", *shadow_cr0);
75 } else if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
76 PrintDebug("MOV2CR0\n");
78 if (info->cpu_mode == LONG) {
82 struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
83 struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.src_operand.operand);
85 PrintDebug("OperandVal = %x, length=%d\n", *new_cr0, dec_instr.src_operand.size);
88 PrintDebug("Old CR0=%x\n", *real_cr0);
92 if (info->shdw_pg_mode == SHADOW_PAGING) {
93 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
95 PrintDebug("Old Shadow CR0=%x\n", *shadow_cr0);
99 *shadow_cr0 = *new_cr0;
102 if (get_mem_mode(info) == VIRTUAL_MEM) {
103 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
105 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
107 info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
111 PrintDebug("New Shadow CR0=%x\n",*shadow_cr0);
113 PrintDebug("New CR0=%x\n", *real_cr0);
116 } else if (opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
118 struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
122 if (info->shdw_pg_mode == SHADOW_PAGING) {
123 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
127 PrintError("Unhandled opcode in handle_cr0_write\n");
131 info->rip += dec_instr.instr_length;
137 // First attempt = 253 lines
138 // current = 51 lines
139 int handle_cr0_read(struct guest_info * info) {
142 struct x86_instr dec_instr;
144 if (info->mem_mode == PHYSICAL_MEM) {
145 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
147 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
150 /* The IFetch will already have faulted in the necessary bytes for the full instruction
152 // I think we should inject a GPF into the guest
153 PrintError("Could not read instruction (ret=%d)\n", ret);
158 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
159 PrintError("Could not decode instruction\n");
163 if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
164 struct cr0_32 * virt_cr0 = (struct cr0_32 *)(dec_instr.dst_operand.operand);
165 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
167 PrintDebug("MOVCR2\n");
168 PrintDebug("CR0 at 0x%x\n", real_cr0);
170 if (info->shdw_pg_mode == SHADOW_PAGING) {
171 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
173 *virt_cr0 = *real_cr0;
176 PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
177 PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
178 } else if (opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
179 struct cr0_real *real_cr0= (struct cr0_real*)&(info->ctrl_regs.cr0);
180 struct cr0_real *virt_cr0 = (struct cr0_real *)(dec_instr.dst_operand.operand);
181 char cr0_val = *(char*)real_cr0 & 0x0f;
183 PrintDebug("SMSW\n");
185 PrintDebug("CR0 at 0x%x\n", real_cr0);
187 *(char *)virt_cr0 &= 0xf0;
188 *(char *)virt_cr0 |= cr0_val;
191 PrintError("Unhandled opcode in handle_cr0_read\n");
195 info->rip += dec_instr.instr_length;
202 // First Attempt = 256 lines
203 // current = 65 lines
204 int handle_cr3_write(struct guest_info * info) {
207 struct x86_instr dec_instr;
209 if (info->mem_mode == PHYSICAL_MEM) {
210 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
212 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
215 /* The IFetch will already have faulted in the necessary bytes for the full instruction
217 // I think we should inject a GPF into the guest
218 PrintError("Could not read instruction (ret=%d)\n", ret);
223 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
224 PrintError("Could not decode instruction\n");
228 if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
230 PrintDebug("MOV2CR3\n");
232 PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
234 if (info->shdw_pg_mode == SHADOW_PAGING) {
235 struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
236 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
237 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
241 PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n",
242 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
245 cached = cache_page_tables32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
248 PrintError("CR3 Cache failed\n");
250 } else if (cached == 0) {
253 PrintDebug("New CR3 is different - flushing shadow page table\n");
255 delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
257 shadow_pt = create_new_shadow_pt32();
259 shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
261 PrintDebug("Reusing cached shadow Page table\n");
264 shadow_cr3->pwt = new_cr3->pwt;
265 shadow_cr3->pcd = new_cr3->pcd;
268 *guest_cr3 = *new_cr3;
270 PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n",
271 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
273 if (info->mem_mode == VIRTUAL_MEM) {
274 // If we aren't in paged mode then we have to preserve the identity mapped CR3
275 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
279 PrintError("Unhandled opcode in handle_cr3_write\n");
283 info->rip += dec_instr.instr_length;
290 // first attempt = 156 lines
291 // current = 36 lines
292 int handle_cr3_read(struct guest_info * info) {
295 struct x86_instr dec_instr;
297 if (info->mem_mode == PHYSICAL_MEM) {
298 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
300 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
303 /* The IFetch will already have faulted in the necessary bytes for the full instruction
305 // I think we should inject a GPF into the guest
306 PrintError("Could not read instruction (ret=%d)\n", ret);
311 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
312 PrintError("Could not decode instruction\n");
316 if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
317 PrintDebug("MOVCR32\n");
318 struct cr3_32 * virt_cr3 = (struct cr3_32 *)(dec_instr.dst_operand.operand);
320 PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
322 if (info->shdw_pg_mode == SHADOW_PAGING) {
323 *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
325 *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
328 PrintError("Unhandled opcode in handle_cr3_read\n");
332 info->rip += dec_instr.instr_length;