Received: by 2002:a89:288:0:b0:1f7:eeee:6653 with SMTP id j8csp73724lqh; Mon, 6 May 2024 11:39:57 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWM0mYIi7lqCilDmNoq6NoBJ4o1Q65nzYf7vYiYi/4qDPJ0t3nPhb/+nyzz8Zsl3ZEi6WdiR5BCckAW12K74qLMBwxQDGNREvV0WCOj8Q== X-Google-Smtp-Source: AGHT+IHdxTGH+0FfpaRgwDQkcliFP8Q6rCQQk3+gLg6/k6gQzVDuv4J4muyj90PqLP3hkau4wwuA X-Received: by 2002:a05:6a21:8887:b0:1a7:9812:3680 with SMTP id tb7-20020a056a21888700b001a798123680mr11685710pzc.40.1715020797066; Mon, 06 May 2024 11:39:57 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1715020797; cv=pass; d=google.com; s=arc-20160816; b=ZvuWtrsI7bz1zmVHN8PEQnnxaANWV223LHFNuiBAmABgVrb2Th7wskeX9mlXOv2HQN YQ0cDEIy9C7URvVJDkaMnGEJZfzY+r6HTPFug2m6qqclaVOvZBiuuK79X8wC8Qu54e5V YgMu5Nf5vLdMlbzsWV6VFwTvVK1nPTvl19sC2T8jW3kMVWFGuPmGC86c/K1LbM7s7ZIC bgVe5U+JWt4KOTlVmyRC7TtF3iKHMxqy3PLiGQJ1z650ch3L/te90J+Sb8kagGvbaMCY P0e+JFgaElKKcLhcq7vSWGITxoiUGREPhPj/5Ddy7cM/EpWvLefzg/4ooUkezAqv7FMV i/hg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=w8f3lBeQk2XEjbT4L/jOmz1YZT+8xclpFPOobCMH54g=; fh=39c7xHRXKGHRweehzLnY8wn6iHFCUfmQLOpmt3ijdwY=; b=hyrKPjT8y0CcHgc1FD/f39tbYyFFGJTkTgTlgQxEgNqJm05ph27uBNOefa2/ENmKI0 7T1p8Y6uqQrQiTAUvhH6UzOuV1CHvAeQMAD2vkqCyDVyHH1LI+uSxNto6DOO58yBYh3I 3pHlPpJZMfLD7dcI+O8U8nkO2dWV8FeLpccAQoIeBirPthifZMUJAJizTxZj1QFeLxtW T6Y8w7PAmlwY8jTuwCSV2lRLdczoVYamOyK6tlLwlCZndl4D+/7lBk4Up+Uo/2D5tfYV hesdaJuhaOQwXMhmd9EcSJaDYSaXD46Sb4H1MO4nqQkI1ixeRf2zJqaCPDl7a1kTMuh0 b2zg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=ly9yZ3VF; arc=pass (i=1 spf=pass spfdomain=intel.com dkim=pass dkdomain=intel.com dmarc=pass fromdomain=intel.com); spf=pass (google.com: domain of linux-kernel+bounces-170300-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-170300-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.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 j14-20020aa78dce000000b006eced1a16absi7010957pfr.200.2024.05.06.11.39.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 May 2024 11:39:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-170300-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=@intel.com header.s=Intel header.b=ly9yZ3VF; arc=pass (i=1 spf=pass spfdomain=intel.com dkim=pass dkdomain=intel.com dmarc=pass fromdomain=intel.com); spf=pass (google.com: domain of linux-kernel+bounces-170300-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-170300-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.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 1D6EBB23B93 for ; Mon, 6 May 2024 18:37:36 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CF8101598E0; Mon, 6 May 2024 18:36:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ly9yZ3VF" Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B0B35158DC4; Mon, 6 May 2024 18:36:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715020588; cv=none; b=QovhV4FyhtzRq2e5G5sVGFAjAVwn3yvcLmFs/5uLpADbapudChK7UR5EYqg3Ao96lT7qTsO2F8UcdjKsyy0dQXTuPKEx4wTkvhFI08dDbxZb3Sbr9pHof0lCWPDLvtIaYDGAhCMeQG5p64CBDoInnf6q275FC4K1/MRq47IWLx0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715020588; c=relaxed/simple; bh=+ihVkDEpUcnmzb/O05pN4MdzfyRmDXtshitm8PzX3qw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kE+qHZKtt4ZhrB+eBMGs7PeHEDPH/rMjkaFaXd09iCXSMgdJT7HokRXw5p62fL//V6sogJU04s08PSA99ebj/2C32cnw4bec3FiLvzXo5L+iWBaxsDFsS9HB13FL5Yrcjc9v+wmtQ7absBm4ane+lymo4ARB3IzK6FbFm3Xzch0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=ly9yZ3VF; arc=none smtp.client-ip=192.198.163.9 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1715020587; x=1746556587; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+ihVkDEpUcnmzb/O05pN4MdzfyRmDXtshitm8PzX3qw=; b=ly9yZ3VF2hBxg241uO8E4r76K7/Voru+5P9NA5+X6vXNQ6d2JsdZwViQ TMplP6zCM314TH/XHwUmyTt5Xhfk5t4T2rAHZy3pIS91SY5h0VRVhAyMO 70FWzSzafeyGVmeUSjYQt2m5leFtkuS8LH7NSVI9i2SLSTsE8tBOKSmx+ M8rcTk+KwCoghd5aA5Z7PCw8OCAXM6fGeGCySM1AeL/Bqd9wAS+P6SNsu G5Jey11eiDvSNa0aUsPxSInDB4oaQZGJbKmnB1YEkqkS8xNun+yApyWrl OqTkWGRT1UxoExynSUtGvzPCdeNcAGO3bU6YcHwoNL8Ym3SzyMOXH7Aul A==; X-CSE-ConnectionGUID: tAH24pjiQDKLHFYkRqtUaQ== X-CSE-MsgGUID: C/U9IQm+TbO4Dwkt+nvYcw== X-IronPort-AV: E=McAfee;i="6600,9927,11065"; a="21455756" X-IronPort-AV: E=Sophos;i="6.07,259,1708416000"; d="scan'208";a="21455756" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 May 2024 11:36:10 -0700 X-CSE-ConnectionGUID: 28MLq4amRrmBCBVBu2azjQ== X-CSE-MsgGUID: 7spJvhH4T9Sp5VixDIx9sA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,259,1708416000"; d="scan'208";a="28237815" Received: from rchatre-ws.ostc.intel.com ([10.54.69.144]) by fmviesa008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 May 2024 11:36:10 -0700 From: Reinette Chatre To: isaku.yamahata@intel.com, pbonzini@redhat.com, erdemaktas@google.com, vkuznets@redhat.com, seanjc@google.com, vannapurve@google.com, jmattson@google.com, mlevitsk@redhat.com, xiaoyao.li@intel.com, chao.gao@intel.com, rick.p.edgecombe@intel.com, yuan.yao@intel.com Cc: reinette.chatre@intel.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V6 4/4] KVM: selftests: Add test for configure of x86 APIC bus frequency Date: Mon, 6 May 2024 11:35:58 -0700 Message-Id: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Isaku Yamahata Test if the APIC bus clock frequency is the expected configured value. 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. Suggested-by: Sean Christopherson Signed-off-by: Isaku Yamahata Reviewed-by: Maxim Levitsky Co-developed-by: Reinette Chatre Signed-off-by: Reinette Chatre --- Changes v6: - Use vm_create() wrapper instead of open coding it. (Zide) - Improve grammar of test description. (Zide) Changes v5: - Update to new name of capability KVM_CAP_X86_APIC_BUS_FREQUENCY -> KVM_CAP_X86_APIC_BUS_CYCLES_NS. (Xiaoyao Li) Changes v4: - Rework changelog. - Add Sean's "Suggested-by" to acknowledge guidance received in https://lore.kernel.org/all/ZU0BASXWcck85r90@google.com/ - Add copyright. - Add test description to file header. - Consistent capitalization for acronyms. - Rebase to kvm-x86/next. - Update to v4 change of providing bus clock rate in nanoseconds. - Add a "TEST_REQUIRE()" for the new capability so that the test can work on kernels that do not support the new capability. - Address checkpatch warnings and use tabs instead of spaces in header file to match existing code. Changes v3: - Use 1.5GHz instead of 1GHz as frequency. Changes v2: - Newly added. --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/x86_64/apic.h | 7 + .../kvm/x86_64/apic_bus_clock_test.c | 166 ++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/apic_bus_clock_test.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 6de9994971c9..52039d7c8dd5 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -111,6 +111,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/vmx_invalid_nested_guest_state TEST_GEN_PROGS_x86_64 += x86_64/vmx_set_nested_state_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_tsc_adjust_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_nested_tsc_scaling_test +TEST_GEN_PROGS_x86_64 += x86_64/apic_bus_clock_test TEST_GEN_PROGS_x86_64 += x86_64/xapic_ipi_test TEST_GEN_PROGS_x86_64 += x86_64/xapic_state_test TEST_GEN_PROGS_x86_64 += x86_64/xcr0_cpuid_test diff --git a/tools/testing/selftests/kvm/include/x86_64/apic.h b/tools/testing/selftests/kvm/include/x86_64/apic.h index bed316fdecd5..b0d2fc62e172 100644 --- a/tools/testing/selftests/kvm/include/x86_64/apic.h +++ b/tools/testing/selftests/kvm/include/x86_64/apic.h @@ -60,6 +60,13 @@ #define APIC_VECTOR_MASK 0x000FF #define APIC_ICR2 0x310 #define SET_APIC_DEST_FIELD(x) ((x) << 24) +#define APIC_LVT0 0x350 +#define APIC_LVT_TIMER_ONESHOT (0 << 17) +#define APIC_LVT_TIMER_PERIODIC (1 << 17) +#define APIC_LVT_TIMER_TSCDEADLINE (2 << 17) +#define APIC_TMICT 0x380 +#define APIC_TMCCT 0x390 +#define APIC_TDCR 0x3E0 void apic_disable(void); void xapic_enable(void); 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..56eb686144c6 --- /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). + */ +#define _GNU_SOURCE /* for program_invocation_short_name */ + +#include "apic.h" +#include "test_util.h" + +/* + * Pick one convenient value, 1.5GHz. No special meaning and different from + * the default value, 1GHz. + */ +#define TSC_HZ (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) + +/* + * Pick a typical value, 25MHz. Different enough from the default value, 1GHz. + */ +#define APIC_BUS_CLOCK_FREQ (25 * 1000 * 1000ULL) + +static void guest_code(void) +{ + /* + * Possible TDCR values and its divide count. Used to modify APIC + * timer frequency. + */ + struct { + u32 tdcr; + u32 divide_count; + } tdcrs[] = { + {0x0, 2}, + {0x1, 4}, + {0x2, 8}, + {0x3, 16}, + {0x8, 32}, + {0x9, 64}, + {0xa, 128}, + {0xb, 1}, + }; + + u32 tmict, tmcct; + u64 tsc0, tsc1; + int i; + + asm volatile("cli"); + + xapic_enable(); + + /* + * Setup one-shot timer. The vector does not matter because the + * interrupt does 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); + } + + 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(1); + 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. + */ + 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