blob: f25c95f4ea6a5406a70adb3f1d2392bb66409512 [file] [log] [blame] [edit]
// Copyright 2018 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/ktrace.h>
#include <hypervisor/ktrace.h>
#include <kernel/thread.h>
#if defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc99-designator"
#endif
static StringRef* const vcpu_meta[] = {
[VCPU_INTERRUPT] = "wait:interrupt"_stringref,
[VCPU_PORT] = "wait:port"_stringref,
};
static_assert((sizeof(vcpu_meta) / sizeof(vcpu_meta[0])) == VCPU_META_COUNT,
"vcpu_meta array must match enum VcpuMeta");
static StringRef* const vcpu_exit[] = {
#if ARCH_ARM64
[VCPU_UNDERFLOW_MAINTENANCE_INTERRUPT] = "exit:underflow_maintenance_interrupt"_stringref,
[VCPU_PHYSICAL_INTERRUPT] = "exit:physical_interrupt"_stringref,
[VCPU_WFI_INSTRUCTION] = "exit:wfi_instruction"_stringref,
[VCPU_WFE_INSTRUCTION] = "exit:wfe_instruction"_stringref,
[VCPU_SMC_INSTRUCTION] = "exit:smc_instruction"_stringref,
[VCPU_SYSTEM_INSTRUCTION] = "exit:system_instruction"_stringref,
[VCPU_INSTRUCTION_ABORT] = "exit:instruction_abort"_stringref,
[VCPU_DATA_ABORT] = "exit:data_abort"_stringref,
[VCPU_SERROR_INTERRUPT] = "exit:serror_interrupt"_stringref,
#elif ARCH_X86
[VCPU_EXCEPTION_OR_NMI] = "exit:exception_or_nmi"_stringref,
[VCPU_EXTERNAL_INTERRUPT] = "exit:external_interrupt"_stringref,
[VCPU_INTERRUPT_WINDOW] = "exit:interrupt_window"_stringref,
[VCPU_CPUID] = "exit:cpuid"_stringref,
[VCPU_HLT] = "exit:hlt"_stringref,
[VCPU_CONTROL_REGISTER_ACCESS] = "exit:control_register_access"_stringref,
[VCPU_IO_INSTRUCTION] = "exit:io_instruction"_stringref,
[VCPU_RDMSR] = "exit:rdmsr"_stringref,
[VCPU_WRMSR] = "exit:wrmsr"_stringref,
[VCPU_VM_ENTRY_FAILURE] = "exit:vm_entry_failure"_stringref,
[VCPU_EPT_VIOLATION] = "exit:ept_violation"_stringref,
[VCPU_XSETBV] = "exit:xsetbv"_stringref,
[VCPU_PAUSE] = "exit:pause"_stringref,
[VCPU_VMCALL] = "exit:vmcall"_stringref,
#endif
[VCPU_NOT_SUPPORTED] = "exit:not_supported"_stringref,
[VCPU_FAILURE] = "exit:failure"_stringref,
};
#if defined(__clang__)
#pragma GCC diagnostic pop
#endif
static_assert((sizeof(vcpu_exit) / sizeof(vcpu_exit[0])) == VCPU_EXIT_COUNT,
"vcpu_exit array must match enum VcpuExit");
void ktrace_vcpu(uint32_t tag, VcpuMeta meta) {
if (unlikely(ktrace_tag_enabled(tag))) {
const Thread* current_thread = Thread::Current::Get();
const fxt::ThreadRef thread{current_thread->pid(), current_thread->tid()};
const fxt::StringRef category{"kernel:vcpu"_stringref->GetId()};
const fxt::Argument arg{fxt::StringRef{"meta #"_stringref->GetId()}, meta};
const auto name = meta < VCPU_META_COUNT ? fxt::StringRef(vcpu_meta[meta]->GetId())
: fxt::StringRef("vcpu meta"_stringref->GetId());
if (tag == TAG_VCPU_BLOCK) {
fxt_duration_begin(tag, current_ticks(), thread, category, name, arg);
} else if (tag == TAG_VCPU_UNBLOCK) {
fxt_duration_end(tag, current_ticks(), thread, category, name, arg);
}
}
}
void ktrace_vcpu_exit(VcpuExit exit, uint64_t exit_address) {
if (unlikely(ktrace_tag_enabled(TAG_VCPU_EXIT))) {
const Thread* current_thread = Thread::Current::Get();
const fxt::ThreadRef thread{current_thread->pid(), current_thread->tid()};
const fxt::StringRef category{"kernel:vcpu"_stringref->GetId()};
const fxt::Argument<fxt::ArgumentType::kUint64, fxt::RefType::kId> addr_arg{
fxt::StringRef{"exit_address"_stringref->GetId()}, exit_address};
const fxt::StringRef name{"vcpu"_stringref->GetId()};
if (exit < VCPU_EXIT_COUNT) {
const fxt::Argument exit_type_arg{fxt::StringRef{"exit_address"_stringref->GetId()},
fxt::StringRef{vcpu_exit[exit]->GetId()}};
fxt_duration_end(TAG_VCPU_EXIT, current_ticks(), thread, category, name, addr_arg,
exit_type_arg);
} else {
const fxt::Argument exit_type_arg{fxt::StringRef("exit_address"_stringref->GetId()), exit};
fxt_duration_end(TAG_VCPU_EXIT, current_ticks(), thread, category, name, addr_arg,
exit_type_arg);
}
}
}