blob: a7a9729655aff5d7795140d31fa0352f5d43cc6f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.virtual.resources.handlers;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.IVirtualMachineEventHandler;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.data.VcpuStateValues;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.model.IVirtualEnvironmentModel;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.model.VirtualCPU;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.model.VirtualMachine;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.virtual.resources.VmAttributes;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
/**
* Handle events coming from a qemu/kvm hypervisor
*
* @author Geneviève Bastien
*/
public class QemuKvmEventHandler implements IVirtualMachineEventHandler {
private Map<IKernelAnalysisEventLayout, Set<String>> fRequiredEvents = new HashMap<>();
/**
* Constructor
*/
public QemuKvmEventHandler() {
// Nothing to do
}
@Override
public Set<String> getRequiredEvents(IKernelAnalysisEventLayout layout) {
Set<String> events = fRequiredEvents.get(layout);
if (events == null) {
events = new HashSet<>();
events.addAll(layout.eventsKVMEntry());
events.addAll(layout.eventsKVMExit());
fRequiredEvents.put(layout, events);
}
return events;
}
/**
* Handle the event for a Qemu/kvm model
*
* @param ss
* The state system builder to fill
* @param event
* The event to handle
*/
@Override
public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event, IVirtualEnvironmentModel virtEnv, IKernelAnalysisEventLayout layout) {
String eventName = event.getName();
long ts = event.getTimestamp().toNanos();
if (layout.eventsKVMEntry().contains(eventName)) {
// The vcpu is exiting hypervisor mode
handleKvmEvent(ss, ts, event, virtEnv, i -> i & ~VcpuStateValues.VCPU_VMM);
} else if (layout.eventsKVMExit().contains(eventName)) {
// The vcpu is entering hypervisor mode
handleKvmEvent(ss, ts, event, virtEnv, i -> i | VcpuStateValues.VCPU_VMM);
}
}
private static void handleKvmEvent(ITmfStateSystemBuilder ss, long ts, ITmfEvent event, IVirtualEnvironmentModel virtEnv, Function<Integer, Integer> fctNewVal) {
HostThread ht = IVirtualMachineEventHandler.getCurrentHostThread(event, ts);
if (ht == null) {
return;
}
VirtualCPU vcpu = virtEnv.getVirtualCpu(event, ht);
if (vcpu == null) {
// The current thread has a vcpu configured, ignore
return;
}
/* Add the hypervisor flag to the status */
VirtualMachine vm = vcpu.getVm();
int curStatusQuark = ss.getQuarkAbsoluteAndAdd(VmAttributes.VIRTUAL_MACHINES, vm.getHostId(),
vcpu.getCpuId().toString(), VmAttributes.STATUS);
int prevStatus = Math.max(VcpuStateValues.VCPU_UNKNOWN, ss.queryOngoingState(curStatusQuark).unboxInt());
int value = Objects.requireNonNull(fctNewVal.apply(prevStatus));
ss.modifyAttribute(ts, value, curStatusQuark);
}
}