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>
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));
16 if (info->cpu_mode == REAL) {
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);
23 // I think we should inject a GPF into the guest
24 PrintDebug("Could not read instruction (ret=%d)\n", ret);
28 while (is_prefix_byte(instr[index])) {
32 if ((instr[index] == cr_access_byte) &&
33 (instr[index + 1] == lmsw_byte) &&
34 (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
37 addr_t second_operand;
38 struct cr0_real *old_cr0;
39 struct cr0_real *new_cr0;
40 operand_type_t addr_type;
46 old_cr0 = (struct cr0_real*)&(guest_state->cr0);
49 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
52 if (addr_type == REG_OPERAND) {
53 new_cr0 = (struct cr0_real *)first_operand;
54 } else if (addr_type == MEM_OPERAND) {
57 if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
62 new_cr0 = (struct cr0_real *)host_addr;
64 // error... don't know what to do
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;
74 new_cr0_val = *(char*)(new_cr0) & 0x0f;
77 if (info->page_mode == SHADOW_PAGING) {
78 struct cr0_real * virt_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
80 /* struct cr0_real is only 4 bits wide,
81 * so we can overwrite the old_cr0 without worrying about the shadow fields
83 *(char*)old_cr0 &= 0xf0;
84 *(char*)old_cr0 |= new_cr0_val;
86 *(char*)virt_cr0 &= 0xf0;
87 *(char*)virt_cr0 |= new_cr0_val;
89 // for now we just pass through....
90 *(char*)old_cr0 &= 0xf0;
91 *(char*)old_cr0 |= new_cr0_val;
94 PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
96 PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
97 } else if ((instr[index] == cr_access_byte) &&
98 (instr[index + 1] == clts_byte)) {
101 // unsupported instruction, UD the guest
106 } else if (info->cpu_mode == PROTECTED) {
110 PrintDebug("Protected Mode write to CR0\n");
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);
115 // I think we should inject a GPF into the guest
116 PrintDebug("Could not read instruction (ret=%d)\n", ret);
120 while (is_prefix_byte(instr[index])) {
124 if ((instr[index] == cr_access_byte) &&
125 (instr[index + 1] == mov_to_cr_byte)) {
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;
135 old_cr0 = (struct cr0_32*)&(guest_state->cr0);
137 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
140 if (addr_type == REG_OPERAND) {
141 new_cr0 = (struct cr0_32 *)first_operand;
142 } else if (addr_type == MEM_OPERAND) {
145 if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
150 new_cr0 = (struct cr0_32 *)host_addr;
152 // error... don't know what to do
157 if (info->page_mode == SHADOW_PAGING) {
158 struct cr0_32 * virt_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
160 if ((new_cr0->pg == 1) && (virt_cr0->pg == 0)){
161 info->cpu_mode = PROTECTED_PG;
163 // Activate Shadow Paging
166 *virt_cr0 = *new_cr0;
177 PrintDebug("Unknown Mode write to CR0\n");
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));
189 if (info->cpu_mode == REAL) {
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);
196 // I think we should inject a GPF into the guest
197 PrintDebug("Could not read instruction (ret=%d)\n", ret);
201 while (is_prefix_byte(instr[index])) {
205 if ((instr[index] == cr_access_byte) &&
206 (instr[index + 1] == smsw_byte) &&
207 (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
209 addr_t first_operand;
210 addr_t second_operand;
211 struct cr0_real *cr0;
212 operand_type_t addr_type;
217 cr0 = (struct cr0_real*)&(guest_state->cr0);
220 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
222 if (addr_type == MEM_OPERAND) {
225 if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
230 first_operand = host_addr;
232 // error... don't know what to do
236 cr0_val = *(char*)cr0 & 0x0f;
239 *(char *)first_operand &= 0xf0;
240 *(char *)first_operand |= cr0_val;