Skip to content

Conversation

@caseywilliams
Copy link
Contributor

Adds a data source for the CPUID instruction that reports the following:

  1. Whether CPUID output indicates that the current machine is a hypervisor
    guest, and
  2. CPUID's reported vendor ID

Updates the existing VirtualBox detector to check CPUID before DMI.

@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 9e1a2f7 on caseywilliams:cpuid into ** on puppetlabs:master**.

@caseywilliams caseywilliams requested a review from branan July 12, 2017 19:16
*/
struct cpuid_registers
{
/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say these comments are redundant, but I think travis will fail if we don't have 100% docs coverage :/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct! 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If they have to be here, maybe we could make them a little more descriptive? Something like "Value from eax register", etc. Still redundant, but slightly less general (I'd argue any field could accurately be annotated with " value" :P).

/**
* Most hypervisors store vendor information in this leaf
*/
constexpr static const unsigned int INFO_LEAF = 0x40000000;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did something require this to be flagged as constexpr? Usually just being a static const should be enough to get the compiler to inline the value, unless it's involved in other constexpr functions

dmi_source.product_name(),
re_virtualbox);
return cpuid_source.vendor() == "VBoxVBoxVBox" ||
re_search(dmi_source.product_name(), re_virtualbox);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

longer-term we're going to want to be able to track which data sources were successful, but this is good until we have a metadata object to work with 👍

bool cpuid_base::has_hypervisor() const
{
auto regs = read_cpuid(1);
return static_cast<bool>(regs.ecx & (1 << 31));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move this value to a constant named HYPERVISOR_PRESENT or something like that?

string cpuid_base::vendor() const
{
auto regs = read_cpuid(INFO_LEAF);
unsigned int result[13] = {regs.ebx, regs.ecx, regs.edx};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be an array of size 4. It needs to be at least 13 /bytes/, not 13 ints

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also be able to initialize the trailing zero in the initializer list:

unsigned int result[4] = {regs.ebx, regs.ecx, regs.edx, 0};


return result;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spurious extra newline

*/
class cpuid_fixture_values : public sources::cpuid_base {
public:
cpuid_fixture_values(sources::cpuid_registers values);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this instead take a map of leaf -> registers, so you can override multiple queries?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that will be much nicer

@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 2cbfd20 on caseywilliams:cpuid into ** on puppetlabs:master**.

Copy link
Contributor

@Magisus Magisus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One suggestion, otherwise looks generally good. Didn't delve super deep into the processor logic, but I like the structure you have here so far. Sidenote: kinda cool to see some of the stuff from my Computer Architecture class showing up in production code :)

A question out of curiosity, why is this method preferred over other methods of virtualization detection? Is it more reliable, or faster, or what?

@caseywilliams
Copy link
Contributor Author

@Magisus Thanks! Calling CPUID (where available) is likely faster than reading DMI files in /sys/class/dmi/id, or running dmidecode (or checking WMI on Windows) - If we can detect the hypervisor with confidence via CPUID, that's probably the fastest way to do it. Realistically though, this order may need to be reconsidered in the future if we want to prioritize collecting more metadata, since CPUID only gives us a single string.

I'll update the comments on those register strings in a minute here.

Adds a data source for the CPUID instruction that reports the following:
1. Whether CPUID output indicates that the current machine is a hypervisor
   guest, and
2. CPUID's reported vendor ID

Updates the existing VirtualBox detector to check CPUID before DMI.
@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 83870f8 on caseywilliams:cpuid into ** on puppetlabs:master**.

@branan branan merged commit cb3d39b into puppetlabs:master Jul 17, 2017
@caseywilliams caseywilliams deleted the cpuid branch November 7, 2017 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants