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.


moving along...
[palacios.git] / palacios / src / geekos / svm_ctrl_regs.c
1 #include <geekos/svm_ctrl_regs.h>
2 #include <geekos/vmm_mem.h>
3 #include <geekos/vmm.h>
4 #include <geekos/vmcb.h>
5 #include <geekos/vmm_emulate.h>
6 #include <geekos/vm_guest_mem.h>
7 #include <geekos/vmm_ctrl_regs.h>
8
9
10 int handle_cr0_write(struct guest_info * info) {
11   //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
12   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
13   char instr[15];
14   
15   
16   if (info->cpu_mode == REAL) {
17     int index = 0;
18     int ret;
19
20     // The real rip address is actually a combination of the rip + CS base 
21     ret = read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr);
22     if (ret != 15) {
23       // I think we should inject a GPF into the guest
24       PrintDebug("Could not read instruction (ret=%d)\n", ret);
25       return -1;
26     }
27
28     while (is_prefix_byte(instr[index])) {
29       index++; 
30     }
31
32     if ((instr[index] == cr_access_byte) && 
33         (instr[index + 1] == lmsw_byte) && 
34         (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
35  
36       addr_t first_operand;
37       addr_t second_operand;
38       struct cr0_real *old_cr0;
39       struct cr0_real *new_cr0;
40       operand_type_t addr_type;
41       char new_cr0_val = 0;
42       // LMSW
43       // decode mod/RM
44       index += 2;
45  
46       old_cr0 = (struct cr0_real*)&(guest_state->cr0);
47
48
49       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
50
51
52       if (addr_type == REG_OPERAND) {
53         new_cr0 = (struct cr0_real *)first_operand;
54       } else if (addr_type == MEM_OPERAND) {
55         addr_t host_addr;
56
57         if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
58           // gpf the guest
59           return -1;
60         }
61
62         new_cr0 = (struct cr0_real *)host_addr;
63       } else {
64         // error... don't know what to do
65         return -1;
66       }
67                  
68       if ((new_cr0->pe == 1) && (old_cr0->pe == 0)) {
69         info->cpu_mode = PROTECTED;
70       } else if ((new_cr0->pe == 0) && (old_cr0->pe == 1)) {
71         info->cpu_mode = REAL;
72       }
73       
74       new_cr0_val = *(char*)(new_cr0) & 0x0f;
75
76
77       if (info->page_mode == SHADOW_PAGING) {
78         struct cr0_real * virt_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
79
80         /* struct cr0_real is only 4 bits wide, 
81          * so we can overwrite the old_cr0 without worrying about the shadow fields
82          */
83         *(char*)old_cr0 &= 0xf0;
84         *(char*)old_cr0 |= new_cr0_val;
85         
86         *(char*)virt_cr0 &= 0xf0;
87         *(char*)virt_cr0 |= new_cr0_val;
88       } else {
89         // for now we just pass through....
90         *(char*)old_cr0 &= 0xf0;
91         *(char*)old_cr0 |= new_cr0_val;
92       }
93
94       PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
95       info->rip += index;
96       PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
97     } else if ((instr[index] == cr_access_byte) && 
98                (instr[index + 1] == clts_byte)) {
99       // CLTS
100     } else {
101       // unsupported instruction, UD the guest
102       return -1;
103     }
104
105
106   } else if (info->cpu_mode == PROTECTED) {
107     int index = 0;
108     int ret;
109
110     PrintDebug("Protected Mode write to CR0\n");
111
112     // The real rip address is actually a combination of the rip + CS base 
113     ret = read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr);
114     if (ret != 0) {
115       // I think we should inject a GPF into the guest
116       PrintDebug("Could not read instruction (ret=%d)\n", ret);
117       return -1;
118     }
119
120     while (is_prefix_byte(instr[index])) {
121       index++; 
122     }
123
124     if ((instr[index] == cr_access_byte) && 
125         (instr[index + 1] == mov_to_cr_byte)) {
126     
127       addr_t first_operand;
128       addr_t second_operand;
129       struct cr0_32 *old_cr0;
130       struct cr0_32 *new_cr0;
131       operand_type_t addr_type;
132
133       index += 2;
134  
135       old_cr0 = (struct cr0_32*)&(guest_state->cr0);
136
137       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
138
139
140       if (addr_type == REG_OPERAND) {
141         new_cr0 = (struct cr0_32 *)first_operand;
142       } else if (addr_type == MEM_OPERAND) {
143         addr_t host_addr;
144
145         if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
146           // gpf the guest
147           return -1;
148         }
149
150         new_cr0 = (struct cr0_32 *)host_addr;
151       } else {
152         // error... don't know what to do
153         return -1;
154       }
155
156
157       if (info->page_mode == SHADOW_PAGING) {
158         struct cr0_32 * virt_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
159
160         if ((new_cr0->pg == 1) && (virt_cr0->pg == 0)){
161           info->cpu_mode = PROTECTED_PG;
162
163           // Activate Shadow Paging
164         }
165
166         *virt_cr0 = *new_cr0;
167         *old_cr0 = *new_cr0;
168       } else {
169         // fill in
170       }
171
172       info->rip += index;
173
174     }
175     
176   } else {
177     PrintDebug("Unknown Mode write to CR0\n");
178     while(1);
179   }
180   return 0;
181 }
182
183
184 int handle_cr0_read(struct guest_info * info) {
185   //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
186   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
187   char instr[15];
188
189   if (info->cpu_mode == REAL) {
190     int index = 0;
191     int ret;
192
193     // The real rip address is actually a combination of the rip + CS base 
194     ret = read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr);
195     if (ret != 15) {
196       // I think we should inject a GPF into the guest
197       PrintDebug("Could not read instruction (ret=%d)\n", ret);
198       return -1;
199     }
200
201     while (is_prefix_byte(instr[index])) {
202       index++; 
203     }
204
205     if ((instr[index] == cr_access_byte) && 
206         (instr[index + 1] == smsw_byte) && 
207         (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
208
209       addr_t first_operand;
210       addr_t second_operand;
211       struct cr0_real *cr0;
212       operand_type_t addr_type;
213       char cr0_val = 0;
214
215       index += 2;
216       
217       cr0 = (struct cr0_real*)&(guest_state->cr0);
218       
219       
220       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
221       
222       if (addr_type == MEM_OPERAND) {
223         addr_t host_addr;
224         
225         if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
226           // gpf the guest
227           return -1;
228         }
229         
230         first_operand = host_addr;
231       } else {
232         // error... don't know what to do
233         return -1;
234       }
235
236       cr0_val = *(char*)cr0 & 0x0f;
237
238
239       *(char *)first_operand &= 0xf0;
240       *(char *)first_operand |= cr0_val;
241
242       info->rip += index;
243
244     }
245
246   }
247
248
249   return 0;
250 }