os.linux: Rename the "kernelanalysis" package to just "kernel"
[deliverable/tracecompass.git] / lttng / org.eclipse.tracecompass.lttng2.kernel.core / src / org / eclipse / tracecompass / internal / lttng2 / kernel / core / analysis / vm / model / qemukvm / QemuKvmVmModel.java
CommitLineData
4a74f111 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2014, 2015 École Polytechnique de Montréal
4a74f111
MG
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Mohamad Gebai - Initial API and implementation
11 * Geneviève Bastien - Initial API and implementation
12 *******************************************************************************/
13
14package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.qemukvm;
15
16import java.util.HashMap;
17import java.util.Map;
18import java.util.Map.Entry;
19import java.util.Set;
20
21import org.eclipse.jdt.annotation.Nullable;
0f7a12d3
AM
22import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
23import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelThreadInformationProvider;
a6145763 24import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread;
4a74f111
MG
25import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.IVirtualMachineModel;
26import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.VirtualCPU;
27import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.VirtualMachine;
4a74f111
MG
28import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
29import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
30import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
31import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
32import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
33import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
34import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperimentUtils;
35
36import com.google.common.collect.ImmutableSet;
37
38/**
39 * The virtual machine model corresponding to the Qemu/KVM hypervisor. It uses
40 * the kvm_exit/kvm_entry events to identify entry to and exit from the
41 * hypervisor. It also requires vmsync_* events from both guests and hosts to
42 * identify which thread from a host belongs to which machine.
43 *
44 * @author Mohamad Gebai
45 */
46public class QemuKvmVmModel implements IVirtualMachineModel {
47
48 private static final String KVM = "kvm_"; //$NON-NLS-1$
49
50 /* Associate a host's thread to a virtual CPU */
51 private final Map<HostThread, VirtualCPU> fTidToVcpu = new HashMap<>();
52 /* Associate a host's thread to a virtual machine */
53 private final Map<HostThread, VirtualMachine> fTidToVm = new HashMap<>();
54 /* Maps a virtual machine name to a virtual machine */
55 private final Map<String, VirtualMachine> fKnownMachines = new HashMap<>();
56
57 private final TmfExperiment fExperiment;
58
0e4f957e 59 static final ImmutableSet<String> REQUIRED_EVENTS = ImmutableSet.of(
4a74f111
MG
60 QemuKvmStrings.KVM_ENTRY,
61 QemuKvmStrings.KVM_EXIT,
62 QemuKvmStrings.VMSYNC_GH_GUEST,
63 QemuKvmStrings.VMSYNC_GH_HOST,
64 QemuKvmStrings.VMSYNC_HG_GUEST,
65 QemuKvmStrings.VMSYNC_HG_HOST
0e4f957e 66 );
4a74f111
MG
67
68 /**
69 * Constructor
70 *
71 * @param exp
72 * The experiment this model applies to
73 */
74 public QemuKvmVmModel(TmfExperiment exp) {
75 fExperiment = exp;
76 }
77
78 @Override
79 public @Nullable VirtualMachine getCurrentMachine(ITmfEvent event) {
80 final String hostId = event.getTrace().getHostId();
81 VirtualMachine machine = fKnownMachines.get(hostId);
82 if (machine != null) {
83 return machine;
84 }
85
86 /*
87 * TODO: This model wouldn't support a machine (same hostId) being both
88 * a guest and a host
89 */
90
91 /*
92 * This code path would be used only at the beginning of the analysis.
93 * Once all the hostIds have been associated with a virtual machine, the
94 * machines are all cached and the method returns earlier
95 */
96 /* Try to get the virtual machine from the event */
578716e6 97 String eventName = event.getName();
4a74f111
MG
98 if (eventName.startsWith(KVM)) {
99 /* Only the host machine has kvm_* events, so this is a host */
100 machine = VirtualMachine.newHostMachine(hostId);
101 } else if (eventName.equals(QemuKvmStrings.VMSYNC_GH_GUEST) || eventName.equals(QemuKvmStrings.VMSYNC_HG_GUEST)) {
102 /* Those events are only present in the guests */
103 TmfEventField field = (TmfEventField) event.getContent();
104 ITmfEventField data = field.getField(QemuKvmStrings.VM_UID_PAYLOAD);
105 if (data != null) {
106 machine = VirtualMachine.newGuestMachine((Long) data.getValue(), hostId);
107 }
108 }
109 if (machine != null) {
110 /* Associate the machine to the hostID here, for cached access later */
111 fKnownMachines.put(hostId, machine);
112 }
113 return machine;
114 }
115
116 @Override
117 public Set<String> getRequiredEvents() {
118 return REQUIRED_EVENTS;
119 }
120
121 private @Nullable VirtualMachine findVmFromParent(ITmfEvent event, HostThread ht) {
122 /*
123 * Maybe the parent of the current thread has a VM associated, see if we
124 * can infer the VM for this thread
125 */
6d16f5a9 126 KernelAnalysisModule module = getLttngKernelModuleFor(ht.getHost());
4a74f111
MG
127 if (module == null) {
128 return null;
129 }
130
e363eae1 131 Integer ppid = KernelThreadInformationProvider.getParentPid(module, ht.getTid(), event.getTimestamp().getValue());
4a74f111
MG
132 if (ppid == null) {
133 return null;
134 }
135
136 HostThread parentHt = new HostThread(ht.getHost(), ppid);
137 VirtualMachine vm = fTidToVm.get(parentHt);
138 if (vm == null) {
139 return null;
140 }
141 fTidToVm.put(ht, vm);
142
143 return vm;
144 }
145
146 @Override
147 public @Nullable VirtualCPU getVCpuExitingHypervisorMode(ITmfEvent event, HostThread ht) {
578716e6 148 final String eventName = event.getName();
4a74f111
MG
149
150 /* TODO: Use event layouts for this part also */
151 /*
152 * The KVM_ENTRY event means we are entering a virtual CPU, so exiting
153 * hypervisor mode
154 */
155 if (!eventName.equals(QemuKvmStrings.KVM_ENTRY)) {
156 return null;
157 }
158
159 /*
160 * Are we entering the hypervisor and if so, which virtual CPU is
161 * concerned?
162 */
163 VirtualMachine vm = fTidToVm.get(ht);
164 if (vm == null) {
165 vm = findVmFromParent(event, ht);
166 if (vm == null) {
167 return null;
168 }
169 }
170 /* Associate this thread with the virtual CPU that is going to be run */
171 final ITmfEventField content = event.getContent();
172 long vcpu_id = (Long) content.getField(QemuKvmStrings.VCPU_ID).getValue();
173
174 VirtualCPU virtualCPU = VirtualCPU.getVirtualCPU(vm, vcpu_id);
175 fTidToVcpu.put(ht, virtualCPU);
176
177 return virtualCPU;
178 }
179
180 @Override
181 public @Nullable VirtualCPU getVCpuEnteringHypervisorMode(ITmfEvent event, HostThread ht) {
578716e6 182 final String eventName = event.getName();
4a74f111
MG
183 /*
184 * The KVM_EXIT event means we are exiting a virtual CPU, so entering
185 * hypervisor mode
186 */
187 if (!eventName.equals(QemuKvmStrings.KVM_EXIT)) {
188 return null;
189 }
190
191 return getVirtualCpu(ht);
192 }
193
194 @Override
195 public @Nullable VirtualCPU getVirtualCpu(HostThread ht) {
196 return fTidToVcpu.get(ht);
197 }
198
199 @Override
200 public void handleEvent(ITmfEvent event) {
201 /* Is the event handled by this model */
578716e6 202 final String eventName = event.getName();
4a74f111
MG
203 if (!eventName.equals(QemuKvmStrings.VMSYNC_GH_HOST)) {
204 return;
205 }
206
207 final ITmfEventField content = event.getContent();
208 final long ts = event.getTimestamp().getValue();
209 final String hostId = event.getTrace().getHostId();
210
b3867ecc
MAL
211 final Integer cpu = TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event);
212 if (cpu == null) {
4a74f111
MG
213 /* We couldn't find any CPU information, ignore this event */
214 return;
215 }
216
217 /* Find a virtual machine with the vm uid payload value */
218 ITmfEventField data = content.getField(QemuKvmStrings.VM_UID_PAYLOAD);
219 if (data == null) {
220 return;
221 }
222 long vmUid = (Long) data.getValue();
223 for (Entry<String, VirtualMachine> entry : fKnownMachines.entrySet()) {
224 if (entry.getValue().getVmUid() == vmUid) {
225 /*
226 * We found the VM being run, let's associate it with the thread
227 * ID
228 */
6d16f5a9 229 KernelAnalysisModule module = getLttngKernelModuleFor(hostId);
4a74f111
MG
230 if (module == null) {
231 break;
232 }
e363eae1 233 Integer tid = KernelThreadInformationProvider.getThreadOnCpu(module, cpu, ts);
4a74f111
MG
234 if (tid == null) {
235 /*
236 * We do not know which process is running at this point. It
237 * may happen at the beginning of the trace.
238 */
239 break;
240 }
241 HostThread ht = new HostThread(hostId, tid);
242 fTidToVm.put(ht, entry.getValue());
243
244 /*
245 * To make sure siblings are also associated with this VM, also
246 * add an entry for the parent TID
247 */
e363eae1 248 Integer ppid = KernelThreadInformationProvider.getParentPid(module, tid, ts);
4a74f111
MG
249 if (ppid != null) {
250 HostThread parentHt = new HostThread(hostId, ppid);
251 fTidToVm.put(parentHt, entry.getValue());
252 }
253 }
254 }
255 }
256
6d16f5a9
AM
257 private @Nullable KernelAnalysisModule getLttngKernelModuleFor(String hostId) {
258 return TmfExperimentUtils.getAnalysisModuleOfClassForHost(fExperiment, hostId, KernelAnalysisModule.class);
4a74f111
MG
259 }
260
261}
This page took 0.059569 seconds and 5 git commands to generate.