Received: by 2002:ab2:7903:0:b0:1fb:b500:807b with SMTP id a3csp1112944lqj; Mon, 3 Jun 2024 10:25:31 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUc46XhJOhDcC2GkB7IUO+nfHR7qvbbbapTjxINuSwjzYasnwtFocfbLic7+c9eB3PkqpAXEET2OmQ3CKQX7j9uddqBMCh0E48w92UKKg== X-Google-Smtp-Source: AGHT+IF4WEunKrc/Ttq4Oaa5tj25vmoZ+U2+UAv6JypADkAcA8nYZw1ui+A+Ivbxy/n7yWIS8Brs X-Received: by 2002:a17:902:f20a:b0:1f3:4d8f:e5f3 with SMTP id d9443c01a7336-1f6370166cemr77566155ad.15.1717435531101; Mon, 03 Jun 2024 10:25:31 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1717435531; cv=pass; d=google.com; s=arc-20160816; b=Al30ppkvOs7Dod/dYghR64w0pOIVa1o0VcKL3acJ4NUy5ByN96dzEUAah6WBKkmDzY RZmc0PE7/AnhST6zEbDExOWyi0DrzS3uws3SogwlpVCYBl8HWoU7t3yce5pCHJDBxG2y UkFhmYQzz0y5jlivMgM70SqTCWUXsQWk5KO7kDLNk3TDvou8lWrGU+70LIBWC+96qxoT f4Sm+2yJbDMNlgZUnHgCchXreiu+H8DfVk0+IRpxBlgu9IJguB+ZrQroon0zepVj4wgw UgB9wEjiL2LU45IlRGpR+ep6F8x94k462/fg0OHHgz3LGuZ0vIGtK512+z9ukNhh3r7N F5oQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=nJyUAlqpuYEaJF6Nwe4vJ3fr4OIvEC2ccjgFqYcQri8=; fh=4bnP+2k/m629p5dgpboos5wwt6WfVePa/wSXWLUwQn8=; b=jIpa+JEcQ83/AFcHdSdLLz2gxu7H/rIHRFfQ009RmRQRmEkQYD/GSmw/utByjDFRjo A4BMyA9b6r8KvpX1H2NSsL1QmTTCuEEhvHbI7/O7moUCQYclMg5ZSA4kMqGYXTbUDcRe JrDhsjR4kGG/o++qcVU8AkdDH28ljY1ZPhuzWWZ+9HwZszqf6ZmU9L0nbgKPQCruljau 6Iftksq7qNzYmAezrY3JOABIQFsPQMbcpPti4leSd1dVKbPEGWN91RxEhMcAtj8eJImp HIljYLzbynAo8xG7MgoqbGGod9xAueFCwz2Us9GW/Jhmkw5swUUx+wJ96/rj9KsA0pNs P2HA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=J+6qR2EH; arc=pass (i=1 spf=pass spfdomain=flex--seanjc.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-199506-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-199506-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id d9443c01a7336-1f63233cd9dsi69195025ad.110.2024.06.03.10.25.30 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jun 2024 10:25:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-199506-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=J+6qR2EH; arc=pass (i=1 spf=pass spfdomain=flex--seanjc.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-199506-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-199506-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 15F02B217CB for ; Mon, 3 Jun 2024 17:25:19 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 09564136E3E; Mon, 3 Jun 2024 17:25:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="J+6qR2EH" Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 305D978283 for ; Mon, 3 Jun 2024 17:25:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717435507; cv=none; b=sRVYo/kUGWMdUnstq6/gwaTjbKUD96/zKqJei6ZmDfzqXMQyX0H8mM+up7+WfWqA5uPSg4ylIcCWpcAgC6nhaNs8YYPhAz1NxlOLQ5i9oCZeU6pgtMoW5lk+cHWWmTiNGUEMJsjXF/bcEtSsj+/2TPAznpayTgSHsnF20XZiQHc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717435507; c=relaxed/simple; bh=NfQFmHLQ9shxbIA7d2arj8pts8fHfOHHhoWHnlN8OD0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=c2YAcetApMwy4RCqQjBDtf6NjcP9aU3rJryfwoer9n7Ks+ygcOo9JfkxR9CDhLbfbU1foXLacAilmH3hJQfT+2POTZRgQK2uZpxoi3+k4f5MI0zTKKjiC0dr/iYjaP0Vn+T5KrFGMmwEA5MgQ62fGrxr/JlVl9YkbZ/fyok5h7o= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=J+6qR2EH; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-62a27e501d4so2927037b3.3 for ; Mon, 03 Jun 2024 10:25:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1717435505; x=1718040305; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=nJyUAlqpuYEaJF6Nwe4vJ3fr4OIvEC2ccjgFqYcQri8=; b=J+6qR2EHBZPQ8JEgRDYR/TcyUBiZR3B9UZzeUjwl50Ibh3w6zf5hZK5HI1gtaPCkWl Y2TL/AgxhRfSsaAi8rFYLYIjbh5j6Cpwpe9ivh9tDaawnzQC0YsSNLT43Yfz6fTySKD5 jN7aXjitpaD4xRZLZgXREDi8DQ8fLlt5225l2GvRJqNPuRG2lWclZ2FklSmpHteS9AGX tQuQIDjwuEPyUMoeI0lpnOGWwJhKcp7AR+m1F+TyKp3BTjwelg3En7RyE0r8NbPMBHWo A/qPX/Z4Xbo4a8j6f1pMqFWkGsr/e2ibKismdPHxXDjQeeKCqlrEkUGjDFGABKzSLD4p 0DEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717435505; x=1718040305; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=nJyUAlqpuYEaJF6Nwe4vJ3fr4OIvEC2ccjgFqYcQri8=; b=KFFYCLTzDXTcoQwh6qm47PKb2wc/Y/+09XVbN8bS4fKCg/2V2fklQq9izhq4shesqX qFhnvIym5+uZFecACi7RroOhtNxzIahrCBowKs4wqVudIbCw2P9sqEEskiaztkhza2ij slpy3ZMfVNIclYsUpWooQpiQ4r8OL4QbIOH1pbpyjFVDDLXxDPXZoOR5JPbEuYdTtcek IMyvkTz2FM7X65BpehAxuppTccWKI1VADfJCCy4btkUW4ktNvO1owAwgGGPJnyPX6i/q qLGY/zlIb4bGYThPIf8sPFyz3muB5FeOaDjQ90Gsw79NBR4SvmHkfERzO3b6XQAZ4Vvn uwBQ== X-Forwarded-Encrypted: i=1; AJvYcCXv9wyIz9fW9q5WcCJjsmqnIO9928rXNH3722gA5gVN8zW9KOyXz50COG2l+vhM6f228Hux9khHgG7Btg6hJrWcKkMtrRfipbxyR2MB X-Gm-Message-State: AOJu0Ywhjcs467EDdfu1LUT1JaXVGDToDeZX3fFbt9+XpDKyi1o2ZU6F BjK7jDl52bJxLBZIQER4jJfOSY91i/moov+weFuVUfw1i4eUV89zv36PzhCnJV8m/4+aNAbk+0R j3w== X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6902:708:b0:df7:9609:4ce2 with SMTP id 3f1490d57ef6-dfa73d8da89mr726894276.8.1717435505040; Mon, 03 Jun 2024 10:25:05 -0700 (PDT) Date: Mon, 3 Jun 2024 10:25:03 -0700 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: Message-ID: Subject: Re: [PATCH V5 4/4] KVM: selftests: Add test for configure of x86 APIC bus frequency From: Sean Christopherson To: Reinette Chatre Cc: isaku.yamahata@intel.com, pbonzini@redhat.com, erdemaktas@google.com, vkuznets@redhat.com, vannapurve@google.com, jmattson@google.com, mlevitsk@redhat.com, xiaoyao.li@intel.com, chao.gao@intel.com, rick.p.edgecombe@intel.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="us-ascii" On Thu, Apr 25, 2024, Reinette Chatre wrote: > From: Isaku Yamahata > > Test if the APIC bus clock frequency is the expected configured value. This is one of the cases where explicitly calling out "code" by name is extremely valuable. E.g. Test if KVM emulates the APIC bus clock at the expected frequency when userspace configures the frequency via KVM_CAP_X86_APIC_BUS_CYCLES_NS. Set APIC timer's initial count to the maximum value and busy wait for 100 msec (largely arbitrary) using the TSC. Read the APIC timer's "current count" to calculate the actual APIC bus clock frequency based on TSC frequency. > Set APIC timer's initial count to the maximum value and busy wait for 100 > msec (any value is okay) with TSC value. Read the APIC timer's "current > count" to calculate the actual APIC bus clock frequency based on TSC > frequency. > > diff --git a/tools/testing/selftests/kvm/x86_64/apic_bus_clock_test.c b/tools/testing/selftests/kvm/x86_64/apic_bus_clock_test.c > new file mode 100644 > index 000000000000..5100b28228af > --- /dev/null > +++ b/tools/testing/selftests/kvm/x86_64/apic_bus_clock_test.c > @@ -0,0 +1,166 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Test configure of APIC bus frequency. > + * > + * Copyright (c) 2024 Intel Corporation > + * > + * To verify if the APIC bus frequency can be configured this test starts > + * by setting the TSC frequency in KVM, and then: > + * For every APIC timer frequency supported: > + * * In the guest: > + * * * Start the APIC timer by programming the APIC TMICT (initial count > + * register) to the largest value possible to guarantee that it will > + * not expire during the test, > + * * * Wait for a known duration based on previously set TSC frequency, > + * * * Stop the timer and read the APIC TMCCT (current count) register to > + * determine the count at that time (TMCCT is loaded from TMICT when > + * TMICT is programmed and then starts counting down). > + * * In the host: > + * * * Determine if the APIC counts close to configured APIC bus frequency > + * while taking into account how the APIC timer frequency was modified > + * using the APIC TDCR (divide configuration register). I find the asterisks super hard to parse. And I honestly wouldn't bother breaking things down by guest vs. host. History has shown that file comments that are *too* specific eventually become stale, often sooner than later. E.g. it's entirely feasible to do the checking in the guest, not the host. How about this? /* * Copyright (c) 2024 Intel Corporation * * Verify KVM correctly emulates the APIC bus frequency when the VMM configures * the frequency via KVM_CAP_X86_APIC_BUS_CYCLES_NS. Start the APIC timer by * programming TMICT (timer initial count) to the largest value possible (so * that the timer will not expire during the test). Then, after an arbitrary * amount of time has elapsed, verify TMCCT (timer current count) is within 1% * of the expected value based on the time elapsed, the APIC bus frequency, and * the programmed TDCR (timer divide configuration register). */ > + */ > +#define _GNU_SOURCE /* for program_invocation_short_name */ This can now be dropped. > +#include "apic.h" > +#include "test_util.h" > + > +/* > + * Pick one convenient value, 1.5GHz. No special meaning and different from > + * the default value, 1GHz. I have no idea where the 1GHz comes from. KVM doesn't force a default TSC, KVM uses the underlying CPU's frequency. Peeking further ahead, I don't understand why this test sets KVM_SET_TSC_KHZ. That brings in a whole different set of behavior, and that behavior is already verified by tsc_scaling_sync.c. I suspect/assume this test forces a frequency so that it can hardcode the math, but (a) that's odd and (b) x86 selftests really should provide a udelay() so that goofy stuff like this doesn't end up in random tests. > + */ > +#define TSC_HZ (1500 * 1000 * 1000ULL) Definitely do not call this TSC_HZ. Yeah, it's local to this file, but defining generic macros like this is just asking for conflicts, and the value itself has nothing to do with the TSC (it's a raw value). E.g. _if_ we need to keep this, something like #define FREQ_1_5_GHZ (1500 * 1000 * 1000ULL) > + > +/* Wait for 100 msec, not too long, not too short value. */ > +#define LOOP_MSEC 100ULL > +#define TSC_WAIT_DELTA (TSC_HZ / 1000 * LOOP_MSEC) These shouldn't exist. > + > +/* > + * Pick a typical value, 25MHz. Different enough from the default value, 1GHz. > + */ > +#define APIC_BUS_CLOCK_FREQ (25 * 1000 * 1000ULL) Rather than hardcode a single frequency, use 25MHz as the default value but let the user override it via command line. > + asm volatile("cli"); Unless I'm misremembering, the timer still counts when the LVT entry is masked so just mask the IRQ in the LVT. Or rather, keep the entry masked in the LVT. FWIW, you _could_ simply leave APIC_LVT0 at its default value to verify KVM correctly emulates that reset value (masked, one-shot). That'd be mildly amusing, but possibly a net negative from readability, so > + > + xapic_enable(); What about x2APIC? Arguably that's _more_ interesting since it's required for TDX. > + /* > + * Setup one-shot timer. The vector does not matter because the > + * interrupt does not fire. _should_ not fire. > + */ > + xapic_write_reg(APIC_LVT0, APIC_LVT_TIMER_ONESHOT); > + > + for (i = 0; i < ARRAY_SIZE(tdcrs); i++) { > + xapic_write_reg(APIC_TDCR, tdcrs[i].tdcr); > + > + /* Set the largest value to not trigger the interrupt. */ > + tmict = ~0; > + xapic_write_reg(APIC_TMICT, tmict); > + > + /* Busy wait for LOOP_MSEC */ > + tsc0 = rdtsc(); > + tsc1 = tsc0; > + while (tsc1 - tsc0 < TSC_WAIT_DELTA) > + tsc1 = rdtsc(); > + > + /* Read APIC timer and TSC */ > + tmcct = xapic_read_reg(APIC_TMCCT); > + tsc1 = rdtsc(); > + > + /* Stop timer */ > + xapic_write_reg(APIC_TMICT, 0); > + > + /* Report it. */ > + GUEST_SYNC_ARGS(tdcrs[i].divide_count, tmict - tmcct, > + tsc1 - tsc0, 0, 0); Why punt to the host? I don't see any reason why GUEST_ASSERT() wouldn't work here. > + } > + > + GUEST_DONE(); > +} > + > +void test_apic_bus_clock(struct kvm_vcpu *vcpu) > +{ > + bool done = false; > + struct ucall uc; > + > + while (!done) { > + vcpu_run(vcpu); > + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); > + > + switch (get_ucall(vcpu, &uc)) { > + case UCALL_DONE: > + done = true; > + break; > + case UCALL_ABORT: > + REPORT_GUEST_ASSERT(uc); > + break; > + case UCALL_SYNC: { > + u32 divide_counter = uc.args[1]; > + u32 apic_cycles = uc.args[2]; > + u64 tsc_cycles = uc.args[3]; > + u64 freq; > + > + TEST_ASSERT(tsc_cycles > 0, > + "TSC cycles must not be zero."); > + > + /* Allow 1% slack. */ > + freq = apic_cycles * divide_counter * TSC_HZ / tsc_cycles; > + TEST_ASSERT(freq < APIC_BUS_CLOCK_FREQ * 101 / 100, > + "APIC bus clock frequency is too large"); > + TEST_ASSERT(freq > APIC_BUS_CLOCK_FREQ * 99 / 100, > + "APIC bus clock frequency is too small"); > + break; > + } > + default: > + TEST_FAIL("Unknown ucall %lu", uc.cmd); > + break; > + } > + } > +} > + > +int main(int argc, char *argv[]) > +{ > + struct kvm_vcpu *vcpu; > + struct kvm_vm *vm; > + > + TEST_REQUIRE(kvm_has_cap(KVM_CAP_X86_APIC_BUS_CYCLES_NS)); > + > + vm = __vm_create(VM_SHAPE_DEFAULT, 1, 0); > + vm_ioctl(vm, KVM_SET_TSC_KHZ, (void *)(TSC_HZ / 1000)); > + /* > + * KVM_CAP_X86_APIC_BUS_CYCLES_NS expects APIC bus clock rate in > + * nanoseconds and requires that no vCPU is created. Meh, I'd drop this comment. It should be quite obvious that the rate is in nanoseconds. And instead of adding a comment for the vCPU creation, do __vm_enable_cap() again _after_ creating a vCPU and verify it fails with -EINVAL. > + */ > + vm_enable_cap(vm, KVM_CAP_X86_APIC_BUS_CYCLES_NS, > + NSEC_PER_SEC / APIC_BUS_CLOCK_FREQ); > + vcpu = vm_vcpu_add(vm, 0, guest_code); > + > + virt_pg_map(vm, APIC_DEFAULT_GPA, APIC_DEFAULT_GPA); > + > + test_apic_bus_clock(vcpu); > + kvm_vm_free(vm); > +} > -- > 2.34.1 >