1 /* 2 * Copyright (C) 2018-2022 Intel Corporation. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef PROFILING_INTERNAL_H 8 #define PROFILING_INTERNAL_H 9 10 #ifdef PROFILING_ON 11 12 #include <asm/guest/vcpu.h> 13 #include <asm/vm_config.h> 14 15 #define MAX_MSR_LIST_NUM 15U 16 #define MAX_PROFILING_MSR_STORE_NUM 1 17 #define MAX_HV_MSR_LIST_NUM (MSR_AREA_COUNT) 18 #define MAX_GROUP_NUM 1U 19 20 #define COLLECT_PROFILE_DATA 0 21 #define COLLECT_POWER_DATA 1 22 23 #define SEP_BUF_ENTRY_SIZE 32U 24 #define SOCWATCH_MSR_OP 100U 25 26 #define MAGIC_NUMBER 0x99999988U 27 28 enum MSR_CMD_STATUS { 29 MSR_OP_READY = 0, 30 MSR_OP_REQUESTED, 31 MSR_OP_HANDLED 32 }; 33 enum MSR_CMD_TYPE { 34 MSR_OP_NONE = 0, 35 MSR_OP_READ, 36 MSR_OP_WRITE, 37 MSR_OP_READ_CLEAR 38 }; 39 40 enum PMU_MSR_TYPE { 41 PMU_MSR_CCCR = 0, 42 PMU_MSR_ESCR, 43 PMU_MSR_DATA 44 }; 45 typedef enum IPI_COMMANDS { 46 IPI_MSR_OP = 0, 47 IPI_PMU_CONFIG, 48 IPI_PMU_START, 49 IPI_PMU_STOP, 50 IPI_VMSW_CONFIG, 51 IPI_UNKNOWN, 52 } ipi_commands; 53 54 typedef enum SEP_PMU_STATE { 55 PMU_INITIALIZED = 0, 56 PMU_SETUP, 57 PMU_RUNNING, 58 PMU_UNINITIALIZED, 59 PMU_UNKNOWN 60 } sep_pmu_state; 61 62 typedef enum PROFILING_SEP_FEATURE { 63 CORE_PMU_SAMPLING = 0, 64 CORE_PMU_COUNTING, 65 PEBS_PMU_SAMPLING, 66 LBR_PMU_SAMPLING, 67 UNCORE_PMU_SAMPLING, 68 VM_SWITCH_TRACING, 69 MAX_SEP_FEATURE_ID 70 } profiling_sep_feature; 71 72 typedef enum SOCWATCH_STATE { 73 SW_SETUP = 0, 74 SW_RUNNING, 75 SW_STOPPED 76 } socwatch_state; 77 78 typedef enum PROFILING_SOCWATCH_FEATURE { 79 SOCWATCH_COMMAND = 0, 80 SOCWATCH_VM_SWITCH_TRACING, 81 MAX_SOCWATCH_FEATURE_ID 82 } profiling_socwatch_feature; 83 84 struct profiling_version_info { 85 int32_t major; 86 int32_t minor; 87 int64_t supported_features; 88 int64_t reserved; 89 }; 90 91 struct profiling_pcpuid { 92 uint32_t leaf; 93 uint32_t subleaf; 94 uint32_t eax; 95 uint32_t ebx; 96 uint32_t ecx; 97 uint32_t edx; 98 }; 99 100 struct profiling_control { 101 int32_t collector_id; 102 int32_t reserved; 103 uint64_t switches; 104 }; 105 106 struct profiling_vcpu_pcpu_map { 107 int16_t vcpu_id; 108 int16_t pcpu_id; 109 uint32_t apic_id; 110 }; 111 112 struct profiling_vm_info { 113 uint16_t vm_id_num; 114 char vm_name[16]; 115 uint16_t num_vcpus; 116 struct profiling_vcpu_pcpu_map cpu_map[MAX_VCPUS_PER_VM]; 117 }; 118 119 struct profiling_vm_info_list { 120 uint16_t num_vms; 121 struct profiling_vm_info vm_list[CONFIG_MAX_VM_NUM+1]; 122 }; 123 124 struct sw_msr_op_info { 125 uint64_t core_msr[MAX_MSR_LIST_NUM]; 126 uint32_t cpu_id; 127 uint32_t valid_entries; 128 uint16_t sample_id; 129 }; 130 131 struct profiling_msr_op { 132 /* value to write or location to write into */ 133 uint64_t value; 134 /* MSR address to read/write; last entry will have value of -1 */ 135 uint32_t msr_id; 136 /* parameter; usage depends on operation */ 137 uint16_t param; 138 uint8_t msr_op_type; 139 uint8_t reg_type; 140 }; 141 142 struct profiling_msr_ops_list { 143 int32_t collector_id; 144 uint32_t num_entries; 145 int32_t msr_op_state; 146 struct profiling_msr_op entries[MAX_MSR_LIST_NUM]; 147 }; 148 struct profiling_pmi_config { 149 uint32_t num_groups; 150 uint32_t trigger_count; 151 struct profiling_msr_op initial_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 152 struct profiling_msr_op start_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 153 struct profiling_msr_op stop_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 154 struct profiling_msr_op entry_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 155 struct profiling_msr_op exit_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 156 }; 157 158 struct profiling_vmsw_config { 159 int32_t collector_id; 160 struct profiling_msr_op initial_list[MAX_MSR_LIST_NUM]; 161 struct profiling_msr_op entry_list[MAX_MSR_LIST_NUM]; 162 struct profiling_msr_op exit_list[MAX_MSR_LIST_NUM]; 163 }; 164 165 struct guest_vm_info { 166 uint64_t vmenter_tsc; 167 uint64_t vmexit_tsc; 168 uint64_t vmexit_reason; 169 uint64_t guest_rip; 170 uint64_t guest_rflags; 171 uint64_t guest_cs; 172 uint16_t guest_vm_id; 173 int32_t external_vector; 174 }; 175 176 struct profiling_status { 177 uint32_t samples_logged; 178 uint32_t samples_dropped; 179 }; 180 181 struct sep_state { 182 sep_pmu_state pmu_state; 183 184 uint32_t current_pmi_group_id; 185 uint32_t num_pmi_groups; 186 187 struct profiling_msr_op 188 pmi_initial_msr_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 189 struct profiling_msr_op 190 pmi_start_msr_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 191 struct profiling_msr_op 192 pmi_stop_msr_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 193 struct profiling_msr_op 194 pmi_entry_msr_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 195 struct profiling_msr_op 196 pmi_exit_msr_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 197 198 uint32_t current_vmsw_group_id; 199 uint32_t num_msw_groups; 200 struct profiling_msr_op 201 vmsw_initial_msr_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 202 struct profiling_msr_op 203 vmsw_entry_msr_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 204 struct profiling_msr_op 205 vmsw_exit_msr_list[MAX_GROUP_NUM][MAX_MSR_LIST_NUM]; 206 207 /* sep handling statistics */ 208 uint32_t samples_logged; 209 uint32_t samples_dropped; 210 uint32_t valid_pmi_count; 211 uint32_t total_pmi_count; 212 uint32_t total_vmexit_count; 213 uint32_t frozen_well; 214 uint32_t frozen_delayed; 215 uint32_t nofrozen_pmi; 216 217 struct msr_store_entry vmexit_msr_list[MAX_PROFILING_MSR_STORE_NUM + MAX_HV_MSR_LIST_NUM]; 218 uint32_t vmexit_msr_cnt; 219 uint64_t guest_debugctl_value; 220 uint64_t saved_debugctl_value; 221 } __aligned(8); 222 223 struct data_header { 224 int32_t collector_id; 225 uint16_t cpu_id; 226 uint16_t data_type; 227 uint64_t tsc; 228 uint64_t payload_size; 229 uint64_t reserved; 230 } __aligned(SEP_BUF_ENTRY_SIZE); 231 232 #define DATA_HEADER_SIZE ((uint64_t)sizeof(struct data_header)) 233 struct core_pmu_sample { 234 /* context where PMI is triggered */ 235 uint16_t os_id; 236 /* reserved */ 237 uint16_t reserved; 238 /* the task id */ 239 uint32_t task_id; 240 /* instruction pointer */ 241 uint64_t rip; 242 /* the task name */ 243 char task[16]; 244 /* physical cpu ID */ 245 uint32_t cpu_id; 246 /* the process id */ 247 uint32_t process_id; 248 /* perf global status msr value (for overflow status) */ 249 uint64_t overflow_status; 250 /* rflags */ 251 uint32_t rflags; 252 /* code segment */ 253 uint32_t cs; 254 } __aligned(SEP_BUF_ENTRY_SIZE); 255 256 #define CORE_PMU_SAMPLE_SIZE ((uint64_t)sizeof(struct core_pmu_sample)) 257 #define NUM_LBR_ENTRY 32 258 259 struct lbr_pmu_sample { 260 /* LBR TOS */ 261 uint64_t lbr_tos; 262 /* LBR FROM IP */ 263 uint64_t lbr_from_ip[NUM_LBR_ENTRY]; 264 /* LBR TO IP */ 265 uint64_t lbr_to_ip[NUM_LBR_ENTRY]; 266 /* LBR info */ 267 uint64_t lbr_info[NUM_LBR_ENTRY]; 268 } __aligned(SEP_BUF_ENTRY_SIZE); 269 270 #define LBR_PMU_SAMPLE_SIZE ((uint64_t)sizeof(struct lbr_pmu_sample)) 271 struct pmu_sample { 272 /* core pmu sample */ 273 struct core_pmu_sample csample; 274 /* lbr pmu sample */ 275 struct lbr_pmu_sample lsample; 276 } __aligned(SEP_BUF_ENTRY_SIZE); 277 278 struct vm_switch_trace { 279 uint64_t vm_enter_tsc; 280 uint64_t vm_exit_tsc; 281 uint64_t vm_exit_reason; 282 uint16_t os_id; 283 uint16_t reserved; 284 }__aligned(SEP_BUF_ENTRY_SIZE); 285 286 #define VM_SWITCH_TRACE_SIZE ((uint64_t)sizeof(struct vm_switch_trace)) 287 /* 288 * Wrapper containing SEP sampling/profiling related data structures 289 */ 290 struct profiling_info_wrapper { 291 struct profiling_msr_ops_list *msr_node; 292 struct sep_state s_state; 293 struct guest_vm_info vm_info; 294 ipi_commands ipi_cmd; 295 struct pmu_sample p_sample; 296 struct vm_switch_trace vm_trace; 297 socwatch_state soc_state; 298 struct sw_msr_op_info sw_msr_info; 299 spinlock_t sw_lock; 300 } __aligned(8); 301 302 int32_t profiling_get_version_info(struct acrn_vm *vm, uint64_t addr); 303 int32_t profiling_get_pcpu_id(struct acrn_vm *vm, uint64_t addr); 304 int32_t profiling_msr_ops_all_cpus(struct acrn_vm *vm, uint64_t addr); 305 int32_t profiling_vm_list_info(struct acrn_vm *vm, uint64_t addr); 306 int32_t profiling_get_control(struct acrn_vm *vm, uint64_t addr); 307 int32_t profiling_set_control(struct acrn_vm *vm, uint64_t addr); 308 int32_t profiling_configure_pmi(struct acrn_vm *vm, uint64_t addr); 309 int32_t profiling_configure_vmsw(struct acrn_vm *vm, uint64_t addr); 310 void profiling_ipi_handler(void *data); 311 int32_t profiling_get_status_info(struct acrn_vm *vm, uint64_t addr); 312 313 #endif 314 315 #endif /* PROFILING_INTERNAL_H */ 316