Page MenuHomeFreeBSD

bhyve/amd64: Add support for CPUID configuration
Needs ReviewPublic

Authored by rosenfeld_grumpf.hope-2000.org on Tue, Sep 29, 1:08 PM.

Details

Reviewers
None
Group Reviewers
bhyve
Summary

Generate CPUID entries from any given CPUID config options and modify
the emulated CPUID configuration for all VCPUs accordingly.

CPUID options conform to the following form:

-o [vcpu.<vcpuid>.]cpuid.<action>=<parameter>

When a CPUID option is rooted under 'cpuid.' in the config tree, it
defines an entry for the global CPUID configuration, which is applied
to all VCPUs. Any CPUID option rooted under 'vcpu.<vcpuid>.cpuid.'
defines a CPUID configuration entry specifically for the given VCPU.

CPUID generation works in several phases for each VCPU:

  • compile a list of global CPUID modification actions from the global cpuid options (this is done only once)
  • compile a list of per-VCPU CPUID modifications actions
  • build a complete CPUID configuration from the complete set of CPUID information emulated or passed through from the host CPU by VMM
  • apply the global CPUID modification actions followed by the per-VCPU modification actions to the CPUID configuration
  • perform a number of necessary checks and fixups, like restoring APIC IDs, removing unreachable CPUID functions, checking for duplicates
  • check the CPUID configuration against a predefined set of constraints for valid register contents for particular functions and indexes, such as bits that are immutable, are clear-only, or which can only be numerically lowered
  • upload the final CPUID configuration for this VCPU to the VM

The most basic for of CPUID configuration parameter is the register
modification action:

-o [vcpu.<vcpuid>.]cpuid.<leaf>[,<index>][+]=<register-action-list>

<leaf> specifies the CPUID leaf (aka "CPUID function") to create an
entry for, with an optional index specified by <index>. Leaf and index
correspond the EAX and ECX input register values, respectively, when a
CPUID instruction is emulated for the guest.

<register-action-list> is a comma-separated list of actions for
modifying the register values returned by CPUID for the specified leaf
and index. Appending to an existing CPUID configuration parameter will
automatically insert the comma.

Register operations take the following form:

<reg><op><value>

<reg> specifies one of the registers EAX, EBX, ECX, or EDX. <op> is one
of "=" (assignment), "&=" (bit masking), or "|=" (bit setting). <value>
specifies the value to use in the operation. If <value> starts with "~",
the value will be inverted before it is applied to the register. There
can be multiple operations applying to the same registers, they will be
executed in the order specified.

There are also a number of "special actions" to set certain CPUID
values in a more straightforward way:

cpuid.hypervisor:

		Hypervisor identification ("hyperv", "kvm", "vmware",
		"virtualbox", "xen", or a raw 12-character string)

cpuid.vendor: CPU vendor ("intel", "amd", or raw 12-character string)
cpuid.family: CPU family
cpuid.model: CPU model
cpuid.stepping: CPU stepping
cpuid.brand: CPU brand string (48 characters, leaves 0x80000002-5)
cpuid.pkgtype: the package type for AMD CPUs (only "am3" at this time)
cpuid.level: maximum supported CPUID function in the 0x00000000 range
cpuid.xlevel: maximum extended CPUID function in the 0x80000000 range
cpuid.linear: no. of address space bits for linear (virtual) addresses
cpuid.physical: no. of address space bits for physical addresses
cpuid.features: list of features to be enabled or disabled

cpuid.check: Behaviour of the CPUID constraints checks:

		none:	perform no constraints checks
		warn:	issue a warning for failing checks
		fail:	fail VM startup if a check fails (default)
		fix:	modify the value to conform to the constraints
			(implies warn)

cpuid.fallback-style:

		The fallback method for inexistant/unsupported CPUID
		leaves, can be "intel" or "amd". Intel CPUs return the
		values for the highest valid CPUID leaf, while AMD CPUs
		return zeros. This is set automatic based on CPU vendor,
		but it may be overridden manually.

There are three sets of pre-defined CPUID configurations:

x86 architecture levels: x86-64-v4, x86-64-v3, x86-64-v2, x86-64-v1

Intel CPU models: icelake, cascadelake, skylake, broadwell, haswell,

		  ivybridge, sandybridge, westmere, nehalem, core2duo,
		  pentium4, coreduo, pentium3, pentium2, pentiumpro,
		  pentium-mmx, pentium, 486

AMD CPU models: opteron-g5, opteron-g4, opteron-g3, opteron-g2,

		  opteron-g1, athlon-64, athlon-xp, athlon, k6-3+,
		  k6-3, k6-2, k6, k5, 486

A pre-defined CPUID configuration can be selected by adding the option
"model=<config>" to the CPU configuration on the command line:

$ bhyve [...] -c 4,model=x86-64-v2 [...]

Of course, pre-defined CPUID configurations can be further modified by
using additional cpuid.<...> configuration options. It's also possible
to create completely new CPUID configuration files and putting them into
/usr/share/bhyve/cpuid.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 77452
Build 74335: arc lint + arc unit