github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/host/hw/hw_utils.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  
    15  #include "vmm_defs.h"
    16  #include "hw_utils.h"
    17  #include "hw_interlocked.h"
    18  #include "trial_exec.h"
    19  #include "local_apic.h"
    20  #include "8259a_pic.h"
    21  #include "vmm_dbg.h"
    22  #include "file_codes.h"
    23  #define VMM_DEADLOOP()          VMM_DEADLOOP_LOG(HW_UTILS_C)
    24  #define VMM_ASSERT(__condition) VMM_ASSERT_LOG(HW_UTILS_C, __condition)
    25  #ifdef JLMDEBUG
    26  #include "jlmdebug.h"
    27  #endif
    28  
    29  
    30  static UINT64 hw_tsc_ticks_per_second = 0;
    31  
    32  #define IA32_DEBUG_IO_PORT   0x80
    33  
    34  
    35  // Stall (busy loop) for a given time, using the platform's speaker port
    36  // h/w.  Should only be called at initialization, since a guest OS may
    37  // change the platform setting.
    38  void hw_stall(UINT32 stall_usec)
    39  {
    40      UINT32   count;
    41      for(count = 0; count < stall_usec; count ++)
    42          hw_read_port_8(IA32_DEBUG_IO_PORT);
    43  }
    44  
    45  
    46  // Calibrate the internal variable holding the number of TSC ticks pers second.
    47  // Should only be called at initialization, as it relies on hw_stall()
    48  
    49  void hw_calibrate_tsc_ticks_per_second(void)
    50  
    51  {
    52      UINT64 start_tsc;
    53  
    54  
    55      start_tsc = hw_rdtsc();
    56      hw_stall(1000);   // 1 ms
    57      hw_tsc_ticks_per_second = (hw_rdtsc() - start_tsc) * 1000;
    58  }
    59  
    60  // Retrieve the internal variable holding the number of TSC ticks pers second.
    61  // Note that, depending on the CPU and ASCI modes, this may only be used as a
    62  // rough estimate.
    63  
    64  UINT64 hw_get_tsc_ticks_per_second(void)
    65  
    66  {
    67      return hw_tsc_ticks_per_second;
    68  }
    69  
    70  
    71  // Stall (busy loop) for a given time, using the CPU TSC register.
    72  // Note that, depending on the CPU and ASCI modes, the stall accuracy may be
    73  // rough.
    74  
    75  void hw_stall_using_tsc(UINT32 stall_usec)
    76  
    77  {
    78      UINT64   end_tsc;
    79  
    80      VMM_ASSERT(hw_tsc_ticks_per_second != 0);
    81      end_tsc = hw_rdtsc() + 
    82                ((UINT64)stall_usec * hw_tsc_ticks_per_second / (UINT64)1000000);
    83      while (hw_rdtsc() < end_tsc) {
    84          hw_pause();
    85      }
    86  }
    87  
    88  #ifdef INCLUDE_UNUSED_CODE
    89  // Test for ready-to-be-accepted fixed interrupts.
    90  BOOLEAN hw_is_ready_interrupt_exist(void)
    91  {
    92      return local_apic_is_sw_enabled() ?
    93          local_apic_is_ready_interrupt_exist() : pic_is_ready_interrupt_exist();
    94  
    95  //    if (local_apic_is_sw_enabled())
    96  //    {
    97  //        VMM_LOG(mask_anonymous, level_trace,"INTR LAPIC is SW ENABLED\n");
    98  //        if (local_apic_is_ready_interrupt_exist())
    99  //        {
   100  //            VMM_LOG(mask_anonymous, level_trace,"INTR LAPIC intr WAINING\n");
   101  //            return TRUE;
   102  //        }
   103  //        else
   104  //        {
   105  //            VMM_LOG(mask_anonymous, level_trace,"INTR LAPIC intr NO\n");
   106  //            return FALSE;
   107  //        }
   108  //    }
   109  //    else
   110  //    {
   111  //        VMM_LOG(mask_anonymous, level_trace,"INTR LAPIC is SW DISABLED\n");
   112  //        if (pic_is_ready_interrupt_exist())
   113  //        {
   114  //            VMM_LOG(mask_anonymous, level_trace,"INTR **PIC intr WAINING\n");
   115  //            return TRUE;
   116  //        }
   117  //        else
   118  //        {
   119  //            VMM_LOG(mask_anonymous, level_trace,"INTR **PIC intr NO\n");
   120  //            return FALSE;
   121  //        }
   122  //    }
   123  }
   124  #endif
   125  
   126  BOOLEAN hw_wrmsr_safe(UINT32 msr_id, UINT64 value, VECTOR_ID *fault_vector, UINT32 *error_code)
   127  {
   128      BOOLEAN ret;
   129      TRIAL_DATA *p_trial = NULL;
   130  
   131      TRY {
   132          hw_write_msr(msr_id, value);
   133          ret = TRUE;
   134      }
   135      CATCH(p_trial) {
   136          ret = FALSE;
   137          if (NULL != p_trial) {
   138              VMM_LOG(mask_anonymous, level_error,"WRMSR(%P) Failed. FaultVector=%P ErrCode=%P\n",
   139                      msr_id, p_trial->fault_vector, p_trial->error_code);
   140              if (NULL != fault_vector) *fault_vector = p_trial->fault_vector;
   141              if (NULL != error_code) *error_code = p_trial->error_code;
   142          }
   143      }
   144      END_TRY;
   145      return ret;
   146  }
   147  
   148  BOOLEAN hw_rdmsr_safe(UINT32 msr_id, UINT64 *value, VECTOR_ID *fault_vector, UINT32 *error_code)
   149  {
   150      BOOLEAN ret;
   151      TRIAL_DATA *p_trial = NULL;
   152  
   153      TRY {
   154          *value = hw_read_msr(msr_id);
   155          ret = TRUE;
   156      }
   157      CATCH(p_trial) {
   158          ret = FALSE;
   159          if (NULL != p_trial) {
   160              VMM_LOG(mask_anonymous, level_error,"RDMSR[%P] failed. FaultVector=%P ErrCode=%P\n",
   161                      msr_id, p_trial->fault_vector, p_trial->error_code);
   162              if (NULL != fault_vector) *fault_vector = p_trial->fault_vector;
   163              if (NULL != error_code) *error_code = p_trial->error_code;
   164          }
   165      }
   166      END_TRY;
   167      return ret;
   168  }
   169