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