github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/host/hw/em64t/em64t_vmx2.c (about) 1 /* 2 * Copyright (c) 2013 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 #include "vmm_defs.h" 15 #define VMM_NATIVE_VMCALL_SIGNATURE 0x024694D40 16 #ifdef JLMDEBUG 17 #include "bootstrap_print.h" 18 #include "jlmdebug.h" 19 20 UINT64 t_vmcs_save_area[512]; // never bigger than 4KB 21 extern void vmm_print_vmcs_region(UINT64* pu); 22 extern void vmm_vmcs_guest_state_read(UINT64* area); 23 #endif 24 25 extern void gcpu_save_registers(); 26 extern void gcpu_restore_registers(); 27 extern void vmentry_failure_function(ADDRESS); 28 extern void vmm_vmcs_guest_state_read(UINT64* area); 29 30 struct VMEXIT_TIME { 31 UINT64 last_vmexit; 32 UINT64 last_vmentry; 33 UINT64 last_reason; 34 UINT64 last_cpu_id; 35 UINT64 this_vmexit; 36 UINT64 this_vmentry; 37 UINT64 this_reason; 38 UINT64 this_cpu_id; 39 }; 40 41 42 void zero_exit_time(struct VMEXIT_TIME *p) 43 { 44 p->last_vmexit= 0ULL; 45 p->last_vmentry= 0ULL; 46 p->last_reason= 0ULL; 47 p->last_cpu_id= 0ULL; 48 p->this_vmexit= 0ULL; 49 p->this_vmentry= 0ULL; 50 p->this_reason= 0ULL; 51 p->this_cpu_id= 0ULL; 52 } 53 54 55 // Function: Called upon VMEXIT. Saves GP registers, allocates stack 56 // for C-function and calls it. 57 asm( 58 ".text\n" 59 ".globl vmexit_func\n" 60 ".type vmexit_func,@function\n" 61 "vmexit_func:\n" 62 "\tcall gcpu_save_registers\n" 63 // call c-function 64 // QUESTION for Tom: do need to do this mov to rbp? 65 "\tmov %rsp, %rbp\n" 66 "\tsubq $8, %rsp\n" // is this needed? 67 "\tcall vmexit_common_handler\n" 68 "\tjmp .\n" 69 "\tret\n" 70 ); 71 72 73 #ifdef JLMDEBUG 74 // remove: to prevent loops in single guest testing 75 static int count= 0; 76 77 asm( 78 ".text\n" 79 ".globl loop_forever\n" 80 ".type loop_forever, @function\n" 81 "loop_forever:\n" 82 "\tjmp .\n" 83 "\tret\n" 84 ); 85 86 87 extern int vmx_vmread(UINT64 index, UINT64 *value); 88 extern int vmx_vmwrite(UINT64 index, UINT64 value); 89 // fixup control registers and make guest loop forever 90 void fixupvmcs() 91 { 92 UINT64 value; 93 void loop_forever(); 94 UINT16* loop= loop_forever; 95 96 #ifdef JLMDEBUG 97 bprint("fixupvmcs %04x\n", *loop); 98 #endif 99 vmx_vmread(0x681e, &value); // guest_rip 100 *((UINT16*) value)= *loop; // feeb 101 102 vmx_vmread(0x4000, &value); // vmx_pin_controls 103 // vmx_vmwrite(0x4000, value); // vmx_pin_controls 104 105 vmx_vmread(0x4002, &value); // vmx_cpu_controls) 106 // vmx_vmwrite(0x4002, value); // vmx_cpu_controls) 107 108 vmx_vmread(0x4012, &value); // vmx_entry_controls 109 // vmx_vmwrite(0x4012, value); // vmx_entry_controls 110 111 vmx_vmread(0x4002, &value); // vmx_exit_controls 112 // vmx_vmwrite(0x4002, value); // vmx_exit_controls 113 } 114 115 116 #endif 117 118 119 void vmentry_func(UINT32 firsttime) 120 // Function: Called upon VMENTRY. 121 // Arguments: firsttime = 1 if called first time 122 { 123 #ifdef JLMDEBUG 124 // first time print out vmcs 125 if(firsttime) { 126 fixupvmcs(); 127 if(count++>0) 128 LOOP_FOREVER 129 bprint("vmentry_func: %d, vmcs area:\n", firsttime); 130 vmm_vmcs_guest_state_read((UINT64*) t_vmcs_save_area); 131 vmm_print_vmcs_region((UINT64*) t_vmcs_save_area); 132 bprint("I think linux starts at 0x%016llx\n", t_vmcs_save_area[0]); 133 } 134 #endif 135 // Assumption: rflags_arg is still addressable (by %rsp). 136 // The asm file sets rcx to the number of args (1) 137 ADDRESS rflags_arg = 0; 138 139 if(firsttime) { //do_launch 140 gcpu_restore_registers(); 141 asm volatile ( 142 "\t movq $0x6fefc000, %%rsi\n" // hack! --- remove this 143 "\tvmlaunch\n" 144 "\tpushfq\n" // push rflags 145 "\tpop %%rdx\n" 146 "\tmovq %%rdx, %[rflags_arg]\n" 147 :[rflags_arg] "=m" (rflags_arg) 148 ::); // rdx need not be saved 149 } 150 else { //do_resume 151 gcpu_restore_registers(); 152 #ifdef JLMDEBUG 153 bprint("In resume\n"); 154 LOOP_FOREVER 155 #endif 156 asm volatile( 157 // Resume execution of Guest Virtual Machine 158 "\tvmresume\n" 159 "\tpushfq \n" // push rflags 160 "\tpop %%rdx\n" 161 "\tmovq %%rdx, %[rflags_arg]\n" 162 : [rflags_arg] "=m" (rflags_arg) 163 ::); // rdx need not be saved 164 } 165 vmentry_failure_function(rflags_arg); 166 #ifdef JLMDEBUG 167 bprint("after vmentry_failure_function returns\n"); 168 LOOP_FOREVER 169 #endif 170 vmentry_func(0ULL); // 0ULL= FALSE 171 } 172 173 174 // CHECK(JLM) 175 UINT64 hw_vmcall(UINT64 vmcall_id, UINT64 arg1, UINT64 arg2, UINT64 arg3) 176 // Function: VMCALL 177 // uVMM expects the following: 178 { 179 UINT64 result= 0ULL; 180 181 // Original asm file mov r8 -> rsi and r9 ->rdi, not sure why? 182 asm volatile( 183 "\tmovq %[vmcall_id], %%rcx\n" 184 "\tmovq %[arg1], %%rdx\n" 185 "\tmovq %[arg2], %%rdi\n" 186 "\tmovq %[arg3], %%rsi\n" 187 "\tmovq $0x024694D40, %%rax\n" 188 "\tvmcall\n" 189 "\tmovq %%rax, %[result] \n" 190 "\tjmp 2f\n" 191 "1:\n" 192 "\tjmp 1b\n" 193 "2:\n" 194 : [result] "=g" (result) 195 : [vmcall_id] "g" (vmcall_id), [arg1] "g" (arg1), 196 [arg2] "g" (arg2), [arg3] "g" (arg3) 197 : "%rax", "%rdi", "%rsi", "%r8", "%rcx", "%rdx"); 198 return result; 199 } 200 201