blob: 2a45991e2a7ce8ce4b5a227cab1e6a79de4cba4a [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "encoder/system_data.h"
#include <cstring>
#include <utility>
#include "./logging.h"
namespace cobalt {
namespace encoder {
namespace {
#if defined(__x86_64__)
// Invokes the cpuid instruction on X86. |info_type| specifies which query
// we are performing. This is written into register EAX prior to invoking
// cpuid. (The sub-type specifier in register ECX is alwyas set to zero.) The
// results from registers EAX, EBX, ECX, EDX respectively are writtent into the
// four entries of |cpu_info|. See for example the wikipedia article on
// cpuid for more info.
void Cpuid(int info_type, int cpu_info[4]) {
__asm__ volatile("cpuid\n"
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
"=d"(cpu_info[3])
: "a"(info_type), "c"(0));
}
// Invokes Cpuid() and uses the results to populate |cpu|.
void PopuluateCpuInfo(SystemProfile::CPU* cpu) {
// First we invoke Cpuid with info_type = 0 in order to obtain num_ids
// and vendor_name.
int cpu_info[4] = {-1};
Cpuid(0, cpu_info);
int num_ids = cpu_info[0];
// The human-readable vendor name is the concatenation of three substrings
// in fields 1, 3, 2 respectively.
std::swap(cpu_info[2], cpu_info[3]);
cpu->mutable_vendor_name()->resize(3 * sizeof(cpu_info[1]));
std::memcpy(&(*cpu->mutable_vendor_name())[0], &cpu_info[1],
3 * sizeof(cpu_info[1]));
if (num_ids > 0) {
// Then invoke Cpuid again with info_type = 1 in order to obtain
// |signature|.
Cpuid(1, cpu_info);
cpu->set_signature(cpu_info[0]);
}
}
#endif
} // namespace
SystemData::SystemData() { PopulateSystemProfile(); }
void SystemData::PopulateSystemProfile() {
#if defined(__linux__)
system_profile_.set_os(SystemProfile::LINUX);
#elif defined(__Fuchsia__)
system_profile_.set_os(SystemProfile::FUCHSIA);
#else
system_profile_.set_os(SystemProfile::UNKNOWN_OS);
#endif
#if defined(__x86_64__)
system_profile_.set_arch(SystemProfile::X86_64);
PopuluateCpuInfo(system_profile_.mutable_cpu());
#elif defined(__aarch64__)
system_profile_.set_arch(SystemProfile::ARM_64);
// TODO(rudominer) Implement CpuInfo on ARM.
#else
system_profile_.set_arch(SystemProfile::UNKNOWN_ARCH);
#endif
}
} // namespace encoder
} // namespace cobalt