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