Re: [kvm-unit-tests PATCH] x86/apic: Gates test_pv_ipi on KVM cpuid, not test device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I've now got around to testing this patch on Linux/KVM.

The thing I was worried about, my <linux/types.h> wrapper, appears to
work exactly as intended, everything builds nicely on Linux. So that
aspect of the patch is now a matter of taste.

However, I *have* run into a minor snag with this proposed change: the
X86_FEATURE_KVM_PV_SEND_IPI bit isn't actually enabled by default. It
looks like it needs to be specified explicitly as a +kvm-pv-ipi flag
in the -cpu option on the Qemu command line. KVM itself still handles
the IPI hypercall either way, as there's another flag you'd have to
opt into for only handling advertised hypercalls.

I think the cleanest way to fix this is probably to add +kvm-pv-ipi to
the apic-split, x2apic, and xapic test suites in x86/unittests.cfg and
keep the strict feature flag check in the test code. As I understand
it, Qemu will filter the feature bit if the underlying KVM
implementation doesn't support it, so that would appear to give us the
best compatibility, except perhaps for Qemu versions that predate this
flag, which will presumably fail to run the test suites altogether.

Alternatively, we could simply check whether we're running on KVM and
skip the feature bit check entirely - it certainly wouldn't make any
additional assumptions; as of right now, the master branch already
assumes we're running on KVM *and* the KVM implementation supports the
IPI HC. Dropping the feature bit check doesn't make the patch tangibly
smaller though.

I'll wait a couple of days for any other suggestions or objections,
and in the absence of such I'll roll your draft patch, my
modifications, and the x86/unittests.cfg tweaks into a v2 patch and
re-submit. (And I'll tag it with you, Sean, as Co-authored-by:)

Thanks,
Phil

On Thu, 5 Oct 2023 at 22:19, Phil Dennis-Jordan <lists@xxxxxxxxxxxxx> wrote:
>
> On Wed, Sep 27, 2023 at 4:18 PM Sean Christopherson <seanjc@xxxxxxxxxx> wrote:
> > Gah, sorry.  This is why I usually inline patches, I forget to actually att=
> > ach
> > the darn things 50% of the time.
>
> Thanks for that, and apologies for only just getting around to taking
> a closer look. Out of the box, this doesn't build on macOS at least,
> as that's missing <linux/types.h>. I tried going down the rabbit hole
> of pulling that header and its various transitive dependencies in from
> the Linux tree, but ended up in a horrible mess where those headers
> try to define things like bool, which libcflat has already pulled in
> from the standard system headers (on Linux I suspect the libc #include
> guards match up with the stuff in <linux/*>, so there's no issue).
> On macOS, the problem is easy to resolve via a cut-down types.h with a
> minimal set of definitions:
>
> #include <libcflat.h>
> typedef u8  __u8;
> typedef u32 __u32;
> typedef u64 __u64;
> typedef s64 __s64;
>
> …but I assume that breaks things on Linux. I'm thinking something like
> this might work:
>
> #if __LINUX__
> #include_next <linux/types.h>
> #else
> [minimal types.h definitions]
> #endif
>
> But I'm unsure if that's really the direction you'd want to go with
> this? (And I still need to set myself up with a dev environment on a
> physical Linux box that I can test this all on.)
>
> Another option might be a symlinked linux/types.h created by
> ./configure if not running on Linux?
>
>
> On the substance of the patch itself:
>
> >         unsigned long a0 = 0xFFFFFFFF, a1 = 0, a2 = 0xFFFFFFFF, a3 = 0x0;
> > -       if (!test_device_enabled())
> > +       if (!this_cpu_has(X86_FEATURE_KVM_PV_SEND_IPI))
>
> So this check will (erroneously IMO) succeed if we're running on a
> non-KVM hypervisor which happens to expose a flag at bit 11 of ecx on
> CPUID leaf 0x40000001 page 0, right? With this in mind, your earlier
> idea seems better:
>
>         if (!is_hypervisor_kvm() ||
> !this_cpu_has(X86_FEATURE_KVM_PV_SEND_IPI)) {
>
> So I've gone ahead and made an attempt at fixing up your draft
> implementation of is_hypervisor_kvm() below.
>
> The partial struct memcmp in get_hypervisor_cpuid_base is a bit icky;
> I'm not sure if that's worth fixing up at the cost of readability.
>
>
> Thoughts?
>
> (I've attached the full set of WIP changes on top of yours as another
> patch. Feel free to squash it all into one if you decide to run with
> it.)
>
> Thanks,
> Phil
>
>
> diff --git a/lib/x86/processor.h b/lib/x86/processor.h
> index 7a7048f9..3d3930c8 100644
> --- a/lib/x86/processor.h
> +++ b/lib/x86/processor.h
> @@ -240,6 +240,7 @@ static inline bool is_intel(void)
>  #define    X86_FEATURE_XSAVE        (CPUID(0x1, 0, ECX, 26))
>  #define    X86_FEATURE_OSXSAVE        (CPUID(0x1, 0, ECX, 27))
>  #define    X86_FEATURE_RDRAND        (CPUID(0x1, 0, ECX, 30))
> +#define    X86_FEATURE_HYPERVISOR        (CPUID(0x1, 0, ECX, 31))
>  #define    X86_FEATURE_MCE            (CPUID(0x1, 0, EDX, 7))
>  #define    X86_FEATURE_APIC        (CPUID(0x1, 0, EDX, 9))
>  #define    X86_FEATURE_CLFLUSH        (CPUID(0x1, 0, EDX, 19))
> @@ -286,7 +287,8 @@ static inline bool is_intel(void)
>  #define X86_FEATURE_VNMI        (CPUID(0x8000000A, 0, EDX, 25))
>  #define    X86_FEATURE_AMD_PMU_V2        (CPUID(0x80000022, 0, EAX, 0))
>
> -#define X86_FEATURE_KVM_PV_SEND_IPI    (CPUID(KVM_CPUID_FEATURES, 0,
> EAX, KVM_FEATURE_PV_SEND_IPI))
> +#define X86_FEATURE_KVM_PV_SEND_IPI \
> +    (CPUID(KVM_CPUID_FEATURES, 0, EAX, KVM_FEATURE_PV_SEND_IPI))
>
>  static inline bool this_cpu_has(u64 feature)
>  {
> @@ -303,6 +305,40 @@ static inline bool this_cpu_has(u64 feature)
>      return ((*(tmp + (output_reg % 32))) & (1 << bit));
>  }
>
> +static inline u32 get_hypervisor_cpuid_base(const char *sig)
> +{
> +    u32 base;
> +    struct cpuid signature;
> +
> +    if (!this_cpu_has(X86_FEATURE_HYPERVISOR))
> +        return 0;
> +
> +    for (base = 0x40000000; base < 0x40010000; base += 0x100) {
> +        signature = cpuid(base);
> +
> +        if (!memcmp(sig, &signature.b, 12))
> +            return base;
> +    }
> +
> +    return 0;
> +}
> +
> +static inline bool is_hypervisor_kvm(void)
> +{
> +    u32 base = get_hypervisor_cpuid_base(KVM_SIGNATURE);
> +
> +    if (!base)
> +        return false;
> +
> +    /*
> +     * Require that KVM be placed at its default base so that macros can be
> +     * used to query individual KVM feature bits.
> +     */
> +    assert_msg(base == KVM_CPUID_SIGNATURE,
> +           "Expect KVM at its default cpuid base (now at: 0x%x)", base);
> +    return true;
> +}
> +
>  struct far_pointer32 {
>      u32 offset;
>      u16 selector;




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux