github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/dbg/vmx_trace.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 "vmx_trace.h" 16 #include "trace.h" 17 #include "common_libc.h" 18 //#include "vmcs_object.h" 19 #include "vmcs_api.h" 20 #include "scheduler.h" 21 #include "hw_utils.h" 22 #include "vmm_dbg.h" 23 #include "file_codes.h" 24 25 #define __builtin_va_end(p) 26 #define __builtin_stdarg_start(a,b) 27 #define __builtin_va_arg(a,p) 0 28 29 #define VMM_DEADLOOP() VMM_DEADLOOP_LOG(VMX_TRACE_C) 30 #define VMM_ASSERT(__condition) VMM_ASSERT_LOG(VMX_TRACE_C, __condition) 31 32 static VMM_TRACE_STATE vmm_trace_state = VMM_TRACE_DISABLED; 33 34 BOOLEAN vmm_trace_init( UINT32 max_num_guests, UINT32 max_num_guest_cpus) 35 { 36 static BOOLEAN called = FALSE; 37 38 if ( ! called) { 39 called = trace_init(max_num_guests, max_num_guest_cpus); 40 } 41 42 return called; 43 } 44 45 void vmm_trace_state_set(VMM_TRACE_STATE state) 46 { 47 switch (state) { 48 case VMM_TRACE_DISABLED: 49 case VMM_TRACE_ENABLED_RECYCLED: 50 case VMM_TRACE_ENABLED_NON_RECYCLED: 51 trace_set_recyclable(VMM_TRACE_ENABLED_RECYCLED == state); 52 vmm_trace_state = state; 53 break; 54 default: 55 break; 56 } 57 } 58 59 60 static size_t vmm_trace_print_string( const char *format, 61 va_list marker, char *string) 62 { 63 char formatted_string[MAX_STRING_LENGTH]; 64 size_t max_index, length; 65 66 if (VMM_TRACE_DISABLED == vmm_trace_state) { 67 return 0; 68 } 69 70 max_index = vmm_strlen(format); 71 if (max_index >= MAX_STRING_LENGTH) { 72 VMM_DEADLOOP(); 73 } 74 75 vmm_strcpy_s(formatted_string, MAX_STRING_LENGTH, format); 76 formatted_string[max_index] = '\0'; 77 78 length = vmm_vsprintf_s(string, MAX_STRING_LENGTH, formatted_string, marker); 79 if (length > MAX_STRING_LENGTH) { 80 VMM_DEADLOOP(); 81 } 82 return length; 83 } 84 85 86 BOOLEAN vmm_trace_buffer(GUEST_CPU_HANDLE guest_cpu, UINT8 buffer_index, 87 const char *format, ...) 88 { 89 va_list marker; 90 TRACE_RECORD_DATA data; 91 VMCS_OBJECT* vmcs_obj = 0; 92 const VIRTUAL_CPU_ID *virtual_cpu_id = 0; 93 GUEST_ID guest_id = 0; 94 CPU_ID gcpu_id = 0; 95 96 if (VMM_TRACE_DISABLED == vmm_trace_state) { 97 return FALSE; 98 } 99 100 if (guest_cpu == NULL) { 101 VMM_LOG(mask_anonymous, level_trace,"%a %d: Invalid parameter(s): guest_cpu 0x%x\n", 102 __FUNCTION__, __LINE__, guest_cpu); 103 VMM_DEADLOOP(); 104 } 105 106 vmm_memset( &data, 0, sizeof( data )); 107 108 va_start(marker, format); 109 vmm_trace_print_string(format, marker, data.string); 110 va_end(marker); 111 112 vmcs_obj = gcpu_get_vmcs(guest_cpu); 113 virtual_cpu_id = guest_vcpu(guest_cpu); 114 115 if(vmcs_obj != NULL) { 116 data.exit_reason = vmcs_read(vmcs_obj, VMCS_EXIT_INFO_REASON); 117 data.guest_eip = vmcs_read(vmcs_obj, VMCS_GUEST_RIP); 118 } 119 data.tsc = (buffer_index == (MAX_TRACE_BUFFERS - 1))? hw_rdtsc(): 0; 120 121 if(virtual_cpu_id != NULL) { 122 guest_id = virtual_cpu_id->guest_id; 123 gcpu_id = virtual_cpu_id->guest_cpu_id; 124 } 125 126 return trace_add_record(guest_id, gcpu_id, buffer_index, &data); 127 } 128 129 130 BOOLEAN 131 vmm_trace( GUEST_CPU_HANDLE guest_cpu, const char *format, 132 ...) 133 { 134 va_list marker; 135 TRACE_RECORD_DATA data; 136 VMCS_OBJECT* vmcs_obj = 0; 137 const VIRTUAL_CPU_ID *virtual_cpu_id = 0; 138 GUEST_ID guest_id = 0; 139 CPU_ID gcpu_id = 0; 140 141 if (VMM_TRACE_DISABLED == vmm_trace_state) 142 { 143 return FALSE; 144 } 145 146 if (guest_cpu == NULL) { 147 VMM_LOG(mask_anonymous, level_trace,"%a %d: Invalid parameter(s): guest_cpu 0x%x\n", 148 __FUNCTION__, __LINE__, guest_cpu); 149 VMM_DEADLOOP(); 150 } 151 152 vmm_memset( &data, 0, sizeof( data )); 153 154 va_start(marker, format); 155 vmm_trace_print_string(format, marker, data.string); 156 va_end(marker); 157 158 vmcs_obj = gcpu_get_vmcs(guest_cpu); 159 virtual_cpu_id = guest_vcpu(guest_cpu); 160 161 if(vmcs_obj != NULL) { 162 data.exit_reason = vmcs_read(vmcs_obj, VMCS_EXIT_INFO_REASON); 163 data.guest_eip = vmcs_read(vmcs_obj, VMCS_GUEST_RIP); 164 data.tsc = 0; 165 // data.tsc = hw_rdtsc(); 166 } 167 168 if(virtual_cpu_id != NULL) { 169 guest_id = virtual_cpu_id->guest_id; 170 gcpu_id = virtual_cpu_id->guest_cpu_id; 171 } 172 return trace_add_record(guest_id, gcpu_id, 0, &data); 173 } 174 175 176 BOOLEAN 177 vmm_trace_print_all(UINT32 guest_num, char *guest_names[]) 178 { 179 TRACE_RECORD_DATA record_data; 180 UINT32 vm_index = 0, cpu_index = 0, buffer_index = 0, record_index = 0; 181 int cnt = 0; 182 183 184 if (VMM_TRACE_DISABLED == vmm_trace_state) { 185 return FALSE; 186 } 187 trace_lock(); 188 189 VMM_LOG(mask_anonymous, level_trace,"\nTrace Events\n"); 190 191 while (trace_remove_oldest_record(&vm_index, &cpu_index, &buffer_index, &record_index, &record_data)) { 192 char *vm_name; 193 char buffer[5]; 194 195 if (0 == cnt++ % 0x1F) 196 { 197 VMM_LOG(mask_anonymous, level_trace, 198 "Buf Index TSC | VM CPU Exit Guest EIP | Message\n" 199 "-----------------------------+---------------------------------+---------------------\n"); 200 } 201 202 (void)vm_name; 203 if (vm_index < guest_num) { 204 vm_name = guest_names[vm_index]; 205 206 } 207 else { 208 vmm_sprintf_s(buffer, sizeof(buffer), "%4d", vm_index); 209 vm_name = buffer; 210 } 211 212 VMM_LOG(mask_anonymous, level_trace,"%2d %8d %016lx |%4s %1d %4d %018P | %s", 213 buffer_index, record_index, record_data.tsc, vm_name, cpu_index, 214 record_data.exit_reason, record_data.guest_eip, record_data.string); 215 216 217 } 218 219 trace_unlock(); 220 return TRUE; 221 } 222