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 new control register handlers
[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
24
25
26
27 // First Attempt = 494 lines
28 // current = 106 lines
29 int handle_cr0_write(struct guest_info * info) {
30   char instr[15];
31   int ret;
32   struct x86_instr dec_instr;
33
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);
36   } else { 
37     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
38   }
39
40   if (ret != 15) {
41     // I think we should inject a GPF into the guest
42     PrintError("Could not read instruction (ret=%d)\n", ret);
43     return -1;
44   }
45
46   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
47     PrintError("Could not decode instruction\n");
48     return -1;
49   }
50
51
52   if (opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
53     struct cr0_real *real_cr0  = (struct cr0_real*)&(info->ctrl_regs.cr0);
54     struct cr0_real *new_cr0 = (struct cr0_real *)(dec_instr.first_operand.operand);    
55     uchar_t new_cr0_val;
56
57     PrintDebug("LMSW\n");
58
59     new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
60     
61     PrintDebug("OperandVal = %x\n", new_cr0_val);
62
63     PrintDebug("Old CR0=%x\n", *real_cr0);      
64     *(uchar_t*)real_cr0 &= 0xf0;
65     *(uchar_t*)real_cr0 |= new_cr0_val;
66     PrintDebug("New CR0=%x\n", *real_cr0);      
67       
68
69     if (info->shdw_pg_mode == SHADOW_PAGING) {
70       struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
71       
72       PrintDebug(" Old Shadow CR0=%x\n", *shadow_cr0);  
73       *(uchar_t*)shadow_cr0 &= 0xf0;
74       *(uchar_t*)shadow_cr0 |= new_cr0_val;
75       PrintDebug("New Shadow CR0=%x\n", *shadow_cr0);   
76     }
77   } else if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
78     PrintDebug("MOV2CR0\n");
79
80     if (info->cpu_mode == LONG) {
81       // 64 bit registers
82     } else {
83       // 32 bit registers
84         struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
85         struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.second_operand.operand);
86
87         PrintDebug("OperandVal = %x, length=%d\n", *new_cr0, dec_instr.first_operand.size);
88
89
90         PrintDebug("Old CR0=%x\n", *real_cr0);
91         *real_cr0 = *new_cr0;
92         
93
94         if (info->shdw_pg_mode == SHADOW_PAGING) {
95           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
96           
97           PrintDebug("Old Shadow CR0=%x\n", *shadow_cr0);       
98           
99           real_cr0->et = 1;
100           
101           *shadow_cr0 = *new_cr0;
102           shadow_cr0->et = 1;
103           
104           if (get_mem_mode(info) == VIRTUAL_MEM) {
105             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
106             
107             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
108           } else  {
109             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
110             real_cr0->pg = 1;
111           }
112           
113           PrintDebug("New Shadow CR0=%x\n",*shadow_cr0);
114         }
115         PrintDebug("New CR0=%x\n", *real_cr0);
116     }
117
118   } else if (opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
119     // CLTS
120     struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
121         
122     real_cr0->ts = 0;
123
124     if (info->shdw_pg_mode == SHADOW_PAGING) {
125       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
126       shadow_cr0->ts = 0;
127     }
128   } else {
129     PrintError("Unhandled opcode in handle_cr0_write\n");
130     return -1;
131   }
132
133   info->rip += dec_instr.instr_length;
134
135   return 0;
136 }
137
138
139 // First attempt = 253 lines
140 // current = 51 lines
141 int handle_cr0_read(struct guest_info * info) {
142   char instr[15];
143   int ret;
144   struct x86_instr dec_instr;
145
146   if (info->mem_mode == PHYSICAL_MEM) { 
147     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
148   } else { 
149     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
150   }
151
152   if (ret != 15) {
153     // I think we should inject a GPF into the guest
154     PrintError("Could not read instruction (ret=%d)\n", ret);
155     return -1;
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.first_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.first_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 Attemp = 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   if (ret != 15) {
216     // I think we should inject a GPF into the guest
217     PrintError("Could not read instruction (ret=%d)\n", ret);
218     return -1;
219   }
220
221   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
222     PrintError("Could not decode instruction\n");
223     return -1;
224   }
225
226   if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
227
228     PrintDebug("MOV2CR3\n");
229
230     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
231
232     if (info->shdw_pg_mode == SHADOW_PAGING) {
233       struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.second_operand.operand);    
234       struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
235       struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
236       
237       PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
238                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
239       
240       if (!CR3_32_SAME_BASE(new_cr3, guest_cr3)) { 
241         addr_t shadow_pt;
242
243         
244         PrintDebug("New CR3 is different - flushing shadow page table\n");      
245         
246         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
247         
248         shadow_pt =  create_new_shadow_pt32(info);
249         
250         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);    
251       } 
252       
253       shadow_cr3->pwt = new_cr3->pwt;
254       shadow_cr3->pcd = new_cr3->pcd;
255       
256       // What the hell...
257       *guest_cr3 = *new_cr3;
258       
259       PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
260                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
261
262       if (info->mem_mode == VIRTUAL_MEM) {
263         // If we aren't in paged mode then we have to preserve the identity mapped CR3
264         info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
265       }
266     }
267   } else {
268     PrintError("Unhandled opcode in handle_cr3_write\n");
269     return -1;
270   }
271
272   info->rip += dec_instr.instr_length;
273
274   return 0;
275 }
276
277
278
279 // first attempt = 156 lines
280 // current = 36 lines
281 int handle_cr3_read(struct guest_info * info) {
282   char instr[15];
283   int ret;
284   struct x86_instr dec_instr;
285
286   if (info->mem_mode == PHYSICAL_MEM) { 
287     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
288   } else { 
289     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
290   }
291
292   if (ret != 15) {
293     // I think we should inject a GPF into the guest
294     PrintError("Could not read instruction (ret=%d)\n", ret);
295     return -1;
296   }
297
298   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
299     PrintError("Could not decode instruction\n");
300     return -1;
301   }
302
303   if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
304     PrintDebug("MOVCR32\n");
305     struct cr3_32 * virt_cr3 = (struct cr3_32 *)(dec_instr.first_operand.operand);
306
307     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
308
309     if (info->shdw_pg_mode == SHADOW_PAGING) {
310       *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
311     } else {
312       *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
313     }
314   } else {
315     PrintError("Unhandled opcode in handle_cr3_read\n");
316     return -1;
317   }
318
319
320   info->rip += dec_instr.instr_length;
321
322   return 0;
323 }