3
3
*
4
4
* SPDX-License-Identifier: BSD-3-Clause
5
5
*/
6
-
7
6
#ifdef PROFILING_ON
8
7
9
8
#include <hypervisor.h>
10
9
11
10
#define ACRN_DBG_PROFILING 5U
12
11
12
+ #define MAJOR_VERSION 1
13
+ #define MINOR_VERSION 0
14
+
13
15
#define LVT_PERFCTR_BIT_MASK 0x10000U
14
16
17
+ static uint64_t sep_collection_switch ;
18
+
15
19
static uint32_t profiling_pmi_irq = IRQ_INVALID ;
16
20
17
21
static void profiling_initialize_vmsw (void )
@@ -62,7 +66,8 @@ static void profiling_pmi_handler(__unused unsigned int irq, __unused void *data
62
66
/*
63
67
* Performs MSR operations on all the CPU's
64
68
*/
65
- int32_t profiling_msr_ops_all_cpus (__unused struct vm * vm , __unused uint64_t addr )
69
+
70
+ int32_t profiling_msr_ops_all_cpus (__unused struct vm * vm , __unused uint64_t addr )
66
71
{
67
72
/* to be implemented
68
73
* call to smp_call_function profiling_ipi_handler
@@ -73,27 +78,138 @@ static void profiling_pmi_handler(__unused unsigned int irq, __unused void *data
73
78
/*
74
79
* Generate VM info list
75
80
*/
76
- int32_t profiling_vm_list_info (__unused struct vm * vm , __unused uint64_t addr )
81
+ int32_t profiling_vm_list_info (struct vm * vm , uint64_t addr )
77
82
{
78
- /* to be implemented */
83
+ struct vm * tmp_vm ;
84
+ struct vcpu * vcpu ;
85
+ int32_t vm_idx ;
86
+ uint16_t i , j ;
87
+ struct profiling_vm_info_list vm_info_list ;
88
+
89
+ (void )memset ((void * )& vm_info_list , 0U , sizeof (vm_info_list ));
90
+
91
+ dev_dbg (ACRN_DBG_PROFILING , "%s: entering" , __func__ );
92
+
93
+ if (copy_from_gpa (vm , & vm_info_list , addr , sizeof (vm_info_list )) != 0 ) {
94
+ pr_err ("%s: Unable to copy addr from vm\n" , __func__ );
95
+ return - EINVAL ;
96
+ }
97
+
98
+ vm_idx = 0 ;
99
+ vm_info_list .vm_list [vm_idx ].vm_id_num = -1 ;
100
+ (void )memcpy_s ((void * )vm_info_list .vm_list [vm_idx ].vm_name , 4U , "VMM\0" , 4U );
101
+ for (i = 0U ; i < phys_cpu_num ; i ++ ) {
102
+ vm_info_list .vm_list [vm_idx ].cpu_map [i ].vcpu_id = (int32_t )i ;
103
+ vm_info_list .vm_list [vm_idx ].cpu_map [i ].pcpu_id = (int32_t )i ;
104
+ vm_info_list .vm_list [vm_idx ].cpu_map [i ].apic_id
105
+ = (int32_t )per_cpu (lapic_id , i );
106
+ }
107
+ vm_info_list .vm_list [vm_idx ].num_vcpus = (int32_t )i ;
108
+ vm_info_list .num_vms = 1 ;
109
+
110
+ for (j = 0U ; j < CONFIG_MAX_VM_NUM ; j ++ ) {
111
+ tmp_vm = get_vm_from_vmid (j );
112
+ if (tmp_vm == NULL ) {
113
+ break ;
114
+ }
115
+ vm_info_list .num_vms ++ ;
116
+ vm_idx ++ ;
117
+
118
+ vm_info_list .vm_list [vm_idx ].vm_id_num = (int32_t )tmp_vm -> vm_id ;
119
+ (void )memcpy_s ((void * )vm_info_list .vm_list [vm_idx ].guid ,
120
+ 16U , tmp_vm -> GUID , 16U );
121
+ snprintf (vm_info_list .vm_list [vm_idx ].vm_name , 16U , "vm_%d" ,
122
+ tmp_vm -> vm_id , 16U );
123
+ vm_info_list .vm_list [vm_idx ].num_vcpus = 0 ;
124
+ i = 0U ;
125
+ foreach_vcpu (i , tmp_vm , vcpu ) {
126
+ vm_info_list .vm_list [vm_idx ].cpu_map [i ].vcpu_id
127
+ = (int32_t )vcpu -> vcpu_id ;
128
+ vm_info_list .vm_list [vm_idx ].cpu_map [i ].pcpu_id
129
+ = (int32_t )vcpu -> pcpu_id ;
130
+ vm_info_list .vm_list [vm_idx ].cpu_map [i ].apic_id = 0 ;
131
+ vm_info_list .vm_list [vm_idx ].num_vcpus ++ ;
132
+ }
133
+ }
134
+
135
+ if (copy_to_gpa (vm , & vm_info_list , addr , sizeof (vm_info_list )) != 0 ) {
136
+ pr_err ("%s: Unable to copy addr to vm\n" , __func__ );
137
+ return - EINVAL ;
138
+ }
139
+
140
+ dev_dbg (ACRN_DBG_PROFILING , "%s: exiting" , __func__ );
79
141
return 0 ;
80
142
}
81
143
82
144
/*
83
145
* Sep/socwatch profiling version
84
146
*/
85
- int32_t profiling_get_version_info (__unused struct vm * vm , __unused uint64_t addr )
147
+ int32_t profiling_get_version_info (struct vm * vm , uint64_t addr )
86
148
{
87
- /* to be implemented */
149
+ struct profiling_version_info ver_info ;
150
+
151
+ (void )memset ((void * )& ver_info , 0U , sizeof (ver_info ));
152
+
153
+ dev_dbg (ACRN_DBG_PROFILING , "%s: entering" , __func__ );
154
+
155
+ if (copy_from_gpa (vm , & ver_info , addr , sizeof (ver_info )) != 0 ) {
156
+ pr_err ("%s: Unable to copy addr from vm\n" , __func__ );
157
+ return - EINVAL ;
158
+ }
159
+
160
+ ver_info .major = MAJOR_VERSION ;
161
+ ver_info .minor = MINOR_VERSION ;
162
+ ver_info .supported_features = (int64_t )
163
+ ((1U << (uint64_t )CORE_PMU_SAMPLING ) |
164
+ (1U << (uint64_t )CORE_PMU_COUNTING ) |
165
+ (1U << (uint64_t )LBR_PMU_SAMPLING ) |
166
+ (1U << (uint64_t )VM_SWITCH_TRACING ));
167
+
168
+ if (copy_to_gpa (vm , & ver_info , addr , sizeof (ver_info )) != 0 ) {
169
+ pr_err ("%s: Unable to copy addr to vm\n" , __func__ );
170
+ return - EINVAL ;
171
+ }
172
+
173
+ dev_dbg (ACRN_DBG_PROFILING , "%s: exiting" , __func__ );
174
+
88
175
return 0 ;
89
176
}
90
177
91
178
/*
92
179
* Gets type of profiling - sep/socwatch
93
180
*/
94
- int32_t profiling_get_control (__unused struct vm * vm , __unused uint64_t addr )
181
+ int32_t profiling_get_control (struct vm * vm , uint64_t addr )
95
182
{
96
- /* to be implemented */
183
+ struct profiling_control prof_control ;
184
+
185
+ (void )memset ((void * )& prof_control , 0U , sizeof (prof_control ));
186
+
187
+ dev_dbg (ACRN_DBG_PROFILING , "%s: entering" , __func__ );
188
+
189
+ if (copy_from_gpa (vm , & prof_control , addr , sizeof (prof_control )) != 0 ) {
190
+ pr_err ("%s: Unable to copy addr from vm\n" , __func__ );
191
+ return - EINVAL ;
192
+ }
193
+
194
+ switch (prof_control .collector_id ) {
195
+ case COLLECT_PROFILE_DATA :
196
+ prof_control .switches = sep_collection_switch ;
197
+ break ;
198
+ case COLLECT_POWER_DATA :
199
+ break ;
200
+ default :
201
+ pr_err ("%s: unknown collector %d" ,
202
+ __func__ , prof_control .collector_id );
203
+ break ;
204
+ }
205
+
206
+ if (copy_to_gpa (vm , & prof_control , addr , sizeof (prof_control )) != 0 ) {
207
+ pr_err ("%s: Unable to copy addr to vm\n" , __func__ );
208
+ return - EINVAL ;
209
+ }
210
+
211
+ dev_dbg (ACRN_DBG_PROFILING , "%s: exiting" , __func__ );
212
+
97
213
return 0 ;
98
214
}
99
215
@@ -131,9 +247,29 @@ int32_t profiling_configure_vmsw(__unused struct vm *vm, __unused uint64_t addr)
131
247
/*
132
248
* Get the physical cpu id
133
249
*/
134
- int32_t profiling_get_pcpu_id (__unused struct vm * vm , __unused uint64_t addr )
250
+ int32_t profiling_get_pcpu_id (struct vm * vm , uint64_t addr )
135
251
{
136
- /* to be implemented */
252
+ struct profiling_pcpuid pcpuid ;
253
+
254
+ (void )memset ((void * )& pcpuid , 0U , sizeof (pcpuid ));
255
+
256
+ dev_dbg (ACRN_DBG_PROFILING , "%s: entering" , __func__ );
257
+
258
+ if (copy_from_gpa (vm , & pcpuid , addr , sizeof (pcpuid )) != 0 ) {
259
+ pr_err ("%s: Unable to copy addr from vm\n" , __func__ );
260
+ return - EINVAL ;
261
+ }
262
+
263
+ cpuid_subleaf (pcpuid .leaf , pcpuid .subleaf , & pcpuid .eax ,
264
+ & pcpuid .ebx , & pcpuid .ecx , & pcpuid .edx );
265
+
266
+ if (copy_to_gpa (vm , & pcpuid , addr , sizeof (pcpuid )) != 0 ) {
267
+ pr_err ("%s: Unable to copy param to vm\n" , __func__ );
268
+ return - EINVAL ;
269
+ }
270
+
271
+ dev_dbg (ACRN_DBG_PROFILING , "%s: exiting" , __func__ );
272
+
137
273
return 0 ;
138
274
}
139
275
0 commit comments