Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 5c48ce3ee8c894c129011593ec5ba16f45ff54b4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*******************************************************************************
 * 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 v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/

package org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.overhead.handlers;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.annotation.Nullable;
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.analysis.core.model.IHostModel;
import org.eclipse.tracecompass.incubator.analysis.core.model.ModelManager;
import org.eclipse.tracecompass.incubator.callstack.core.instrumented.statesystem.InstrumentedCallStackAnalysis;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.IVirtualMachineEventHandler;
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.overhead.VmOverheadStateProvider;
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 static final String FIELD_EXIT_REASON = "exit_reason"; //$NON-NLS-1$

    private final Map<IKernelAnalysisEventLayout, Set<String>> fRequiredEvents = new HashMap<>();

    private final VmOverheadStateProvider fProvider;

    /**
     * Constructor
     *
     * @param provider
     *            The state provider
     */
    public QemuKvmEventHandler(VmOverheadStateProvider provider) {
        fProvider = provider;
    }

    @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, null, null);
        } else if (layout.eventsKVMExit().contains(eventName)) {
            // The vcpu is entering hypervisor mode
            Long exitReason = event.getContent().getFieldValue(Long.class, FIELD_EXIT_REASON);
            handleKvmEvent(ss, ts, event, virtEnv, VmOverheadStateProvider.STATUS_VMM_MODE, String.valueOf(exitReason));
        }
    }

    private void handleKvmEvent(ITmfStateSystemBuilder ss, long ts, ITmfEvent event, IVirtualEnvironmentModel virtEnv, @Nullable Object level2, @Nullable Object level3) {
        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;
        }

        VirtualMachine vm = vcpu.getVm();
        IHostModel model = ModelManager.getModelFor(vm.getHostId());
        int guestTid = model.getThreadOnCpu(vcpu.getCpuId().intValue(), ts);
        if (guestTid != IHostModel.UNKNOWN_TID) {
            int quark = ss.getQuarkAbsoluteAndAdd(VmOverheadStateProvider.TRACES, vm.getTraceName(), VmOverheadStateProvider.THREADS, VmOverheadStateProvider.buildThreadAttributeName(guestTid, vcpu.getCpuId().intValue()), InstrumentedCallStackAnalysis.CALL_STACK);
            // Just make sure this attribute exists, at the beginning of trace or if lost
            // events, it may not
            ss.getQuarkRelativeAndAdd(quark, VmOverheadStateProvider.LEVEL_1);
            int tidQuark = ss.getQuarkRelativeAndAdd(quark, VmOverheadStateProvider.LEVEL_1);
            if (ss.queryOngoing(tidQuark) == null) {
                HostThread hostThread = new HostThread(event.getTrace().getHostId(), guestTid);
                fProvider.createGuestThreadStatus(ss, hostThread, ts, tidQuark);
            }
            int preemptQuark = ss.getQuarkRelativeAndAdd(quark, VmOverheadStateProvider.LEVEL_2);
            ss.modifyAttribute(ts, level2, preemptQuark);
            int statusQuark = ss.getQuarkRelativeAndAdd(quark, VmOverheadStateProvider.LEVEL_3);
            ss.modifyAttribute(ts, level3, statusQuark);
        }

    }

}

Back to the top