Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added queue implementation
[palacios.git] / palacios / src / palacios / vmm_ctrl_regs.c
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>
7
8
9
10 /* Segmentation is a problem here...
11  *
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...
14  */
15
16
17 #ifndef DEBUG_CTRL_REGS
18 #undef PrintDebug
19 #define PrintDebug(fmt, args...)
20 #endif
21
22
23 // First Attempt = 494 lines
24 // current = 106 lines
25 int handle_cr0_write(struct guest_info * info) {
26   char instr[15];
27   int ret;
28   struct x86_instr dec_instr;
29
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);
32   } else { 
33     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
34   }
35
36   /* The IFetch will already have faulted in the necessary bytes for the full instruction
37     if (ret != 15) {
38     // I think we should inject a GPF into the guest
39     PrintError("Could not read instruction (ret=%d)\n", ret);
40     return -1;
41     }
42   */
43
44   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
45     PrintError("Could not decode instruction\n");
46     return -1;
47   }
48
49
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);      
53     uchar_t new_cr0_val;
54
55     PrintDebug("LMSW\n");
56
57     new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
58     
59     PrintDebug("OperandVal = %x\n", new_cr0_val);
60
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);      
65       
66
67     if (info->shdw_pg_mode == SHADOW_PAGING) {
68       struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
69       
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);   
74     }
75   } else if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
76     PrintDebug("MOV2CR0\n");
77
78     if (info->cpu_mode == LONG) {
79       // 64 bit registers
80     } else {
81       // 32 bit registers
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);
84
85         PrintDebug("OperandVal = %x, length=%d\n", *new_cr0, dec_instr.src_operand.size);
86
87
88         PrintDebug("Old CR0=%x\n", *real_cr0);
89         *real_cr0 = *new_cr0;
90         
91
92         if (info->shdw_pg_mode == SHADOW_PAGING) {
93           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
94           
95           PrintDebug("Old Shadow CR0=%x\n", *shadow_cr0);       
96           
97           real_cr0->et = 1;
98           
99           *shadow_cr0 = *new_cr0;
100           shadow_cr0->et = 1;
101           
102           if (get_mem_mode(info) == VIRTUAL_MEM) {
103             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
104             
105             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
106           } else  {
107             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
108             real_cr0->pg = 1;
109           }
110           
111           PrintDebug("New Shadow CR0=%x\n",*shadow_cr0);
112         }
113         PrintDebug("New CR0=%x\n", *real_cr0);
114     }
115
116   } else if (opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
117     // CLTS
118     struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
119         
120     real_cr0->ts = 0;
121
122     if (info->shdw_pg_mode == SHADOW_PAGING) {
123       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
124       shadow_cr0->ts = 0;
125     }
126   } else {
127     PrintError("Unhandled opcode in handle_cr0_write\n");
128     return -1;
129   }
130
131   info->rip += dec_instr.instr_length;
132
133   return 0;
134 }
135
136
137 // First attempt = 253 lines
138 // current = 51 lines
139 int handle_cr0_read(struct guest_info * info) {
140   char instr[15];
141   int ret;
142   struct x86_instr dec_instr;
143
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);
146   } else { 
147     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
148   }
149
150   /* The IFetch will already have faulted in the necessary bytes for the full instruction
151      if (ret != 15) {
152      // I think we should inject a GPF into the guest
153      PrintError("Could not read instruction (ret=%d)\n", ret);
154      return -1;
155      }
156   */
157
158   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
159     PrintError("Could not decode instruction\n");
160     return -1;
161   }
162   
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);
166     
167     PrintDebug("MOVCR2\n");
168     PrintDebug("CR0 at 0x%x\n", real_cr0);
169
170     if (info->shdw_pg_mode == SHADOW_PAGING) {
171       *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
172     } else {
173       *virt_cr0 = *real_cr0;
174     }
175     
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;
182     
183     PrintDebug("SMSW\n");
184
185     PrintDebug("CR0 at 0x%x\n", real_cr0);
186
187     *(char *)virt_cr0 &= 0xf0;
188     *(char *)virt_cr0 |= cr0_val;
189     
190   } else {
191     PrintError("Unhandled opcode in handle_cr0_read\n");
192     return -1;
193   }
194
195   info->rip += dec_instr.instr_length;
196
197   return 0;
198 }
199
200
201
202 // First Attempt = 256 lines
203 // current = 65 lines
204 int handle_cr3_write(struct guest_info * info) {
205   int ret;
206   char instr[15];
207   struct x86_instr dec_instr;
208
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);
211   } else { 
212     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
213   }
214
215   /* The IFetch will already have faulted in the necessary bytes for the full instruction
216      if (ret != 15) {
217      // I think we should inject a GPF into the guest
218      PrintError("Could not read instruction (ret=%d)\n", ret);
219      return -1;
220      }
221   */
222
223   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
224     PrintError("Could not decode instruction\n");
225     return -1;
226   }
227
228   if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
229
230     PrintDebug("MOV2CR3\n");
231
232     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
233
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);
238       int cached = 0;
239       
240
241       PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
242                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
243       
244
245       cached = cache_page_tables32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
246
247       if (cached == -1) {
248         PrintError("CR3 Cache failed\n");
249         return -1;
250       } else if (cached == 0) {
251         addr_t shadow_pt;
252         
253         PrintDebug("New CR3 is different - flushing shadow page table\n");      
254         
255         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
256         
257         shadow_pt =  create_new_shadow_pt32();
258         
259         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);    
260       } else {
261         PrintDebug("Reusing cached shadow Page table\n");
262       }
263       
264       shadow_cr3->pwt = new_cr3->pwt;
265       shadow_cr3->pcd = new_cr3->pcd;
266       
267       // What the hell...
268       *guest_cr3 = *new_cr3;
269       
270       PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
271                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
272
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;
276       }
277     }
278   } else {
279     PrintError("Unhandled opcode in handle_cr3_write\n");
280     return -1;
281   }
282
283   info->rip += dec_instr.instr_length;
284
285   return 0;
286 }
287
288
289
290 // first attempt = 156 lines
291 // current = 36 lines
292 int handle_cr3_read(struct guest_info * info) {
293   char instr[15];
294   int ret;
295   struct x86_instr dec_instr;
296
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);
299   } else { 
300     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
301   }
302
303   /* The IFetch will already have faulted in the necessary bytes for the full instruction
304      if (ret != 15) {
305      // I think we should inject a GPF into the guest
306      PrintError("Could not read instruction (ret=%d)\n", ret);
307      return -1;
308      }
309   */
310
311   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
312     PrintError("Could not decode instruction\n");
313     return -1;
314   }
315
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);
319
320     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
321
322     if (info->shdw_pg_mode == SHADOW_PAGING) {
323       *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
324     } else {
325       *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
326     }
327   } else {
328     PrintError("Unhandled opcode in handle_cr3_read\n");
329     return -1;
330   }
331
332   info->rip += dec_instr.instr_length;
333
334   return 0;
335 }