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