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