[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] WHPX fixes an issue with CPUID 1 not returning
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [PATCH] WHPX fixes an issue with CPUID 1 not returning CPUID_EXT_HYPERVISOR |
Date: |
Thu, 5 Apr 2018 17:50:20 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 |
On 28/03/2018 22:48, Justin Terry (VM) wrote:
> 1. (As the code is doing now). At partition creation time you can
> register for specific CPUID exits and then respond to the CPUID with
> your custom answer or with the Hypervisor defaults that were forwarded
> to you. Unfortunately, QEMU has no way to know the Hypervisor default
> ahead of time but QEMU can make at least make a runtime decision about
> how to respond.
>
> 2. At partition creation time the platform allows QEMU to inject (set)
> the default responses for specific CPUID exits.
... but it still cannot access the hypervisor defaults, right?
> This can now be done by
> setting the `WHV_X64_CPUID_RESULT` in the `CpuidResultList` of
> `WHV_PARTITION_PROPERTY` to the exit values QEMU wants. So effectively
> you can know the answers ahead of time for any that you set but the
> answers are not dynamic.
>
> The only issues/questions I have there are:
>
> If we use [1] (like the code is now) I don't see any way to keep the
> exits in cpu_x86_cpuid() matched up with the registered exits to WHPX.
You'd have to do that on a case-by-case basis. For example, the number
of leaves can be the minimum of the hypervisor and QEMU values, or just
the QEMU value; for "feature" leaves the results will be the AND of the
QEMU and WHPX features; for the XSAVE/XSAVEC/XSAVES (size, offset)
tuples you have to use WHPX's; for family/model/stepping/name/vendor
your mileage may vary but I suppose you can just use WHPX's; and so on.
You can take a look at target/i386/cpu.c's array feature_word_info and
add a function like
void x86_is_feature_word(uint32_t eax, uint32_t ecx, int reg)
{
for (w = 0; w < FEATURE_WORDS; w++) {
FeatureWordInfo *wi = &feature_word_info[w];
if (eax == wi->cpuid_eax &&
(ecx == wi->cpuid_ecx || wi->cpuid_needs_ecx) &&
reg == wi->cpuid_reg) {
return true;
}
}
return false;
}
so that the code in the end is
switch (eax) {
/* yadda yadda... code to special case leaves whose value
* comes from WHPX.
*/
...
default:
if (x86_is_feature_word(eax, ecx, R_EAX)) {
rax &= vcpu->exit_ctx.CpuidAccess.DefaultResultRax;
}
if (x86_is_feature_word(eax, ecx, R_EBX)) {
rax &= vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;
}
if (x86_is_feature_word(eax, ecx, R_ECX)) {
rax &= vcpu->exit_ctx.CpuidAccess.DefaultResultRcx;
}
if (x86_is_feature_word(eax, ecx, R_EDX)) {
rax &= vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;
}
}
> If we use [2] to inject the answers at creation time WHPX needs access
> to the CPUX86State at accel init which also doesn't seem to be possible
> in QEMU today. WHPX could basically just call cpu_x86_cpuid() for each
> CPUID QEMU cares about and plumb the answer before start. This has the
> best performance as we avoid the additional exits but has an issue in
> that the results must be known ahead of time.
The earliest where you have access to that is x86_cpu_initfn.
Paolo