From nobody Thu Sep 03 17:17:33 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hbR9t5jx8z6q5wL for ; Thu, 03 Sep 2026 17:17:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hbR9t50Vsz3Nss for ; Thu, 03 Sep 2026 17:17:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788455858; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=q0UKasgqej3bs7NK4uoMKa9ErN/HeJ/ohxK/5BnMhAs=; b=OOT6ejxF1zkmja5/Xcwzl5O0jtbOExiB0O8yjKpP56ZBT6LXyFuIatgPzCuCZYOepDyPuv G0shoDMqxQRzMWaT8uXCOGqPZ+Rq1ES/kIPbm1k8/p7dXAhzuzG4kd9LCer5JFEwJPXs2P C237BPUYDKIPOWXO6WzaPLGGQrd8AXxSQhzzZZPvXLPVewLHIFrJJb5M9LhykAlj4OBpxf 1Uw35uofTVJ6bhcMiJTLhjpVc25apU/x7x9oR4ws0uu5HhfKh39/yQeMB/p9PvXcnQ1m9N GIzLqHuoIoBrY5nCUonU44YuMIesvY3sKsJNeMN7qa5fSEJsNxQg05pgvk3WHw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788455858; a=rsa-sha256; cv=none; b=pKOZ+sIr+/NRkFm1knqpOcLnVjxoJCW0uozDUjmWOvS7TXJChiNuHYWqbwmBRaZGUjfVX/ JPA20On54nHmtuIcjZO3VylziQ6QyKgPsMBEP0IplQu2vTOUf/MR0PfJoEF/PIoKUOsxMH yfMd6WoldDtE8yatVagufnzVLttJDojq24eV0r1lSl86Q1R/5+PGbxIpd3ht/bBiLqEPtn 07GEuQV3dPav5kgpml0kbpfoEG6QY7DIqowMrGTbnFQsUeyZjiKWzKAbqGcB2wqZc0hjJi +FU+xcKCTQuI5yTkAlZ08knxd1yfm6OGM6hXM/vxZc24BLjbnJdf1M3IeVsOog== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788455858; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=q0UKasgqej3bs7NK4uoMKa9ErN/HeJ/ohxK/5BnMhAs=; b=SPy4jso1Hat2bnpxV1te2dt6+NLOczfPNu65kJJMtep9sedD10U3DAWpzR4MUWxwMNvFll ii6RXS0MU/r4Nuyds4Nu7vukwUt8PkYR9RXtUl3bSiEGiUQZ1RvsYv7M6wuOBjPNFRT9k3 MkVJ86RAyjBBtOrpoSwy6o66gYoppAfgcJAHN6Lb76bIBr9Jy1Vpk+a2KBwqm5l9/a7QLw TvgudOL9R8VjxdAv/u4pKTIxlGZrFg3nfiOTQs+R7puvGlOTkAgjZfeObDXhdSr2WnBw3W +/oOnJ29CyCu+7PYrd6435KRn2W0R2Ez0elLM1FMc1sMZVx2lVWsQn4GqAqIeg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hbR9t3X4pz79X for ; Thu, 03 Sep 2026 17:17:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3ba7d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 03 Sep 2026 17:17:33 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Andre Silva From: Mitchell Horne Subject: git: e555692d1bbb - main - hwpmc: Add ATF regression tests for hwpmc EXTERROR diagnostics List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mhorne X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e555692d1bbbe8918054746f21013fff6256974e Auto-Submitted: auto-generated Date: Thu, 03 Sep 2026 17:17:33 +0000 Message-Id: <6a99abad.3ba7d.6cd1f42b@gitrepo.freebsd.org> The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=e555692d1bbbe8918054746f21013fff6256974e commit e555692d1bbbe8918054746f21013fff6256974e Author: Andre Silva AuthorDate: 2026-06-12 15:39:16 +0000 Commit: Mitchell Horne CommitDate: 2026-09-03 17:17:24 +0000 hwpmc: Add ATF regression tests for hwpmc EXTERROR diagnostics Root-only ATF program hitting negative allocate/attach/read-write paths and asserting the exterr(3) text. AMD/IBS cases skip without the PMC class; program skips without hwpmc. Additional changes by mhorne@: - Move and rename to the established test directory tests/sys/pmc - Remove broken test amd_missing_pmu_flag; fixed by recent change 6c4d9b9af1a3 - Add ATF_REQUIRE_FEATURE("exterr_strings") to skip the tests on kernels compiled without the strings - Remove arch-conditional compilation; tests are properly gated by PMC class check - Fix copyright formatting Reviewed by: Ali Mashtizadeh Signed-off-by: Andre Silva Co-authored-by: mhorne Sponsored by: AMD Pull Request: https://github.com/freebsd/freebsd-src/pull/2180 --- tests/sys/pmc/Makefile | 5 + tests/sys/pmc/pmc_exterr_test.c | 449 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 454 insertions(+) diff --git a/tests/sys/pmc/Makefile b/tests/sys/pmc/Makefile index c9c138250932..311b2ef6343c 100644 --- a/tests/sys/pmc/Makefile +++ b/tests/sys/pmc/Makefile @@ -4,11 +4,16 @@ ATF_TESTS_C+= pmc_api_test ATF_TESTS_C+= pmc_credexec_test ATF_TESTS_C+= pmc_detach_test ATF_TESTS_C+= pmc_exec_test +ATF_TESTS_C+= pmc_exterr_test ATF_TESTS_C+= pmc_lifecycle_test ATF_TESTS_C+= pmc_log_test ATF_TESTS_C+= pmc_wrap_test +TEST_METADATA.pmc_exterr_test+= required_user="root" + LIBADD+= pmc LIBADD.pmc_detach_test+= pthread +CFLAGS.pmc_exterr_test.c+= -I${SRCTOP}/tests + .include diff --git a/tests/sys/pmc/pmc_exterr_test.c b/tests/sys/pmc/pmc_exterr_test.c new file mode 100644 index 000000000000..bc4d260f2ed4 --- /dev/null +++ b/tests/sys/pmc/pmc_exterr_test.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2026 Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "freebsd_test_suite/macros.h" + +static int +hwpmc_syscall_num(void) +{ + struct module_stat ms; + int modid; + + modid = modfind(PMC_MODULE_NAME); + if (modid < 0) + return (-1); + + ms.version = sizeof(ms); + if (modstat(modid, &ms) < 0) + return (-1); + + return (ms.data.intval); +} + +static int +hwpmc_call(int op, void *arg) +{ + int sc; + + sc = hwpmc_syscall_num(); + if (sc < 0) + return (-1); + + return (syscall(sc, op, arg)); +} + +static void +clear_exterr(void) +{ + char exterr[UEXTERROR_MAXLEN]; + + ATF_REQUIRE_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL) == -1); + ATF_REQUIRE_EQ(0, uexterr_gettext(exterr, sizeof(exterr))); + ATF_REQUIRE_STREQ("", exterr); +} + +static void +require_exterr(const char *needle) +{ + char exterr[UEXTERROR_MAXLEN]; + + ATF_REQUIRE_EQ(0, uexterr_gettext(exterr, sizeof(exterr))); + ATF_REQUIRE_MSG(strstr(exterr, needle) != NULL, + "extended error \"%s\" does not contain \"%s\"", exterr, needle); +} + +static void +require_hwpmc(void) +{ + + if (pmc_init() == 0) + return; + + atf_tc_skip("hwpmc is unavailable: %s", strerror(errno)); +} + +static void +require_class(enum pmc_class class, const char *name) +{ + const struct pmc_cpuinfo *pci; + uint32_t i; + + ATF_REQUIRE_EQ(0, pmc_cpuinfo(&pci)); + for (i = 0; i < pci->pm_nclass; i++) { + if (pci->pm_classes[i].pm_class == class) + return; + } + atf_tc_skip("%s PMCs are unavailable on this system", name); +} + +static void +allocate_soft_pmc(enum pmc_mode mode, int cpu, pmc_id_t *pmcid) +{ + + ATF_REQUIRE_EQ(0, pmc_allocate("SOFT-CLOCK.HARD", mode, 0, cpu, pmcid, + 1)); +} + +ATF_TC_WITHOUT_HEAD(pmcallocate_invalid_mode); +ATF_TC_BODY(pmcallocate_invalid_mode, tc) +{ + struct pmc_op_pmcallocate pa; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_class = PMC_CLASS_SOFT; + pa.pm_mode = (enum pmc_mode)0xff; + pa.pm_cpu = PMC_CPU_ANY; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + require_exterr("Invalid PMC mode"); +} + +ATF_TC_WITHOUT_HEAD(pmcallocate_invalid_cpu); +ATF_TC_BODY(pmcallocate_invalid_cpu, tc) +{ + struct pmc_op_pmcallocate pa; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_class = PMC_CLASS_SOFT; + pa.pm_mode = PMC_MODE_TC; + pa.pm_cpu = (uint32_t)pmc_ncpu(); + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + require_exterr("Invalid PMC CPU"); +} + +ATF_TC_WITHOUT_HEAD(pmcallocate_invalid_flags); +ATF_TC_BODY(pmcallocate_invalid_flags, tc) +{ + struct pmc_op_pmcallocate pa; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_class = PMC_CLASS_SOFT; + pa.pm_mode = PMC_MODE_TC; + pa.pm_cpu = PMC_CPU_ANY; + pa.pm_flags = 1U << 31; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + require_exterr("Invalid PMC flags"); +} + +ATF_TC_WITHOUT_HEAD(pmcattach_system_mode); +ATF_TC_BODY(pmcattach_system_mode, tc) +{ + struct pmc_op_pmcattach pa; + pmc_id_t pmcid; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + clear_exterr(); + allocate_soft_pmc(PMC_MODE_SC, 0, &pmcid); + + memset(&pa, 0, sizeof(pa)); + pa.pm_pmc = pmcid; + pa.pm_pid = getpid(); + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCATTACH, &pa) == -1); + require_exterr("Cannot attach a system-mode PMC"); + + ATF_REQUIRE_EQ(0, pmc_release(pmcid)); +} + +ATF_TC_WITHOUT_HEAD(pmcattach_running_pmc); +ATF_TC_BODY(pmcattach_running_pmc, tc) +{ + struct pmc_op_pmcattach pa; + pmc_id_t pmcid; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + clear_exterr(); + allocate_soft_pmc(PMC_MODE_TC, PMC_CPU_ANY, &pmcid); + ATF_REQUIRE_EQ(0, pmc_start(pmcid)); + + memset(&pa, 0, sizeof(pa)); + pa.pm_pmc = pmcid; + pa.pm_pid = getpid(); + + ATF_REQUIRE_ERRNO(EBUSY, hwpmc_call(PMC_OP_PMCATTACH, &pa) == -1); + require_exterr("PMC must be stopped before attach"); + + ATF_REQUIRE_EQ(0, pmc_stop(pmcid)); + ATF_REQUIRE_EQ(0, pmc_release(pmcid)); +} + +ATF_TC_WITHOUT_HEAD(pmcrw_no_flags); +ATF_TC_BODY(pmcrw_no_flags, tc) +{ + struct pmc_op_pmcrw prw; + pmc_id_t pmcid; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + clear_exterr(); + allocate_soft_pmc(PMC_MODE_TC, PMC_CPU_ANY, &pmcid); + + memset(&prw, 0, sizeof(prw)); + prw.pm_pmcid = pmcid; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCRW, &prw) == -1); + require_exterr("PMCRW requires PMC_F_OLDVALUE"); + + ATF_REQUIRE_EQ(0, pmc_release(pmcid)); +} + +ATF_TC_WITHOUT_HEAD(pmcrw_write_running); +ATF_TC_BODY(pmcrw_write_running, tc) +{ + struct pmc_op_pmcrw prw; + pmc_id_t pmcid; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + clear_exterr(); + allocate_soft_pmc(PMC_MODE_TC, PMC_CPU_ANY, &pmcid); + ATF_REQUIRE_EQ(0, pmc_start(pmcid)); + + memset(&prw, 0, sizeof(prw)); + prw.pm_flags = PMC_F_NEWVALUE; + prw.pm_pmcid = pmcid; + prw.pm_value = 1; + + ATF_REQUIRE_ERRNO(EBUSY, hwpmc_call(PMC_OP_PMCRW, &prw) == -1); + require_exterr("Cannot write a PMC while it is running"); + + ATF_REQUIRE_EQ(0, pmc_stop(pmcid)); + ATF_REQUIRE_EQ(0, pmc_release(pmcid)); +} + +ATF_TC_WITHOUT_HEAD(amd_invalid_subclass); +ATF_TC_BODY(amd_invalid_subclass, tc) +{ + struct pmc_op_pmcallocate pa; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + require_class(PMC_CLASS_K8, "AMD"); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_class = PMC_CLASS_K8; + pa.pm_mode = PMC_MODE_TC; + pa.pm_cpu = PMC_CPU_ANY; + pa.pm_flags = PMC_F_EV_PMU; + pa.pm_md.pm_amd.pm_amd_sub_class = UINT32_MAX; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + require_exterr("No PMC row accepted"); +} + +ATF_TC_WITHOUT_HEAD(amd_invalid_config_bits); +ATF_TC_BODY(amd_invalid_config_bits, tc) +{ + struct pmc_op_pmcallocate pa; + char exterr[UEXTERROR_MAXLEN]; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + require_class(PMC_CLASS_K8, "AMD"); + if (!pmc_pmu_enabled()) + atf_tc_skip("AMD PMU raw allocation path is unavailable"); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_class = PMC_CLASS_K8; + pa.pm_mode = PMC_MODE_TC; + pa.pm_cpu = PMC_CPU_ANY; + pa.pm_flags = PMC_F_EV_PMU; + pa.pm_md.pm_amd.pm_amd_sub_class = PMC_AMD_SUB_CLASS_CORE; + pa.pm_md.pm_amd.pm_amd_config = ~0ULL; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + ATF_REQUIRE_EQ(0, uexterr_gettext(exterr, sizeof(exterr))); + if (strstr(exterr, "No PMC row accepted") != NULL) + atf_tc_skip("AMD core reserved-bit diagnostic was not returned"); + ATF_REQUIRE_MSG(strstr(exterr, + "AMD PMU config has unsupported bits") != NULL, + "extended error \"%s\" does not report core reserved-bit failure", + exterr); +} + +/* + * DF subclass with reserved config bits. On a system with Data Fabric + * PMC support, the DF row matches class+subclass and the config-mask + * check fires with the "AMD PMU config has unsupported bits" diagnostic. + * On a system without DF support every row mismatches subclass and we + * surface "No PMC row accepted"; the test skips in that case rather + * than fail. + */ +ATF_TC_WITHOUT_HEAD(amd_invalid_df_config_bits); +ATF_TC_BODY(amd_invalid_df_config_bits, tc) +{ + struct pmc_op_pmcallocate pa; + char exterr[UEXTERROR_MAXLEN]; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + require_class(PMC_CLASS_K8, "AMD"); + if (!pmc_pmu_enabled()) + atf_tc_skip("AMD PMU raw allocation path is unavailable"); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_class = PMC_CLASS_K8; + pa.pm_mode = PMC_MODE_SC; + pa.pm_cpu = 0; + pa.pm_flags = PMC_F_EV_PMU; + pa.pm_md.pm_amd.pm_amd_sub_class = PMC_AMD_SUB_CLASS_DATA_FABRIC; + pa.pm_md.pm_amd.pm_amd_config = ~0ULL; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + ATF_REQUIRE_EQ(0, uexterr_gettext(exterr, sizeof(exterr))); + if (strstr(exterr, "No PMC row accepted") != NULL) + atf_tc_skip("Data Fabric PMCs are unavailable on this system"); + ATF_REQUIRE_MSG(strstr(exterr, + "AMD PMU config has unsupported bits") != NULL, + "extended error \"%s\" does not report DF reserved-bit failure", + exterr); + fprintf(stderr, "DF reserved-bit allocation: errno=EINVAL exterr=%s\n", + exterr); +} + +ATF_TC_WITHOUT_HEAD(ibs_missing_system_capability); +ATF_TC_BODY(ibs_missing_system_capability, tc) +{ + struct pmc_op_pmcallocate pa; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + require_class(PMC_CLASS_IBS, "IBS"); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_class = PMC_CLASS_IBS; + pa.pm_mode = PMC_MODE_SS; + pa.pm_cpu = 0; + pa.pm_md.pm_ibs.ibs_type = IBS_PMC_OP; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + require_exterr("IBS requires SYSTEM capability"); +} + +/* + * An out-of-range ibs_type is a row discriminator mismatch on every IBS + * row (bare EINVAL), so the generic loop-exhaustion message is surfaced. + */ +ATF_TC_WITHOUT_HEAD(ibs_invalid_type); +ATF_TC_BODY(ibs_invalid_type, tc) +{ + struct pmc_op_pmcallocate pa; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + require_class(PMC_CLASS_IBS, "IBS"); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_caps = PMC_CAP_SYSTEM; + pa.pm_class = PMC_CLASS_IBS; + pa.pm_mode = PMC_MODE_SS; + pa.pm_cpu = 0; + pa.pm_md.pm_ibs.ibs_type = UINT32_MAX; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + require_exterr("No PMC row accepted"); +} + +ATF_TC_WITHOUT_HEAD(ibs_invalid_config_bits); +ATF_TC_BODY(ibs_invalid_config_bits, tc) +{ + struct pmc_op_pmcallocate pa; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + require_class(PMC_CLASS_IBS, "IBS"); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_caps = PMC_CAP_SYSTEM; + pa.pm_class = PMC_CLASS_IBS; + pa.pm_mode = PMC_MODE_SS; + pa.pm_cpu = 0; + pa.pm_md.pm_ibs.ibs_type = IBS_PMC_OP; + pa.pm_md.pm_ibs.ibs_ctl = 1ULL << 58; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + require_exterr("IBS op ctl config"); +} + +ATF_TC_WITHOUT_HEAD(ibs_nonsampling_mode); +ATF_TC_BODY(ibs_nonsampling_mode, tc) +{ + struct pmc_op_pmcallocate pa; + + ATF_REQUIRE_FEATURE("exterr_strings"); + require_hwpmc(); + require_class(PMC_CLASS_IBS, "IBS"); + clear_exterr(); + + memset(&pa, 0, sizeof(pa)); + pa.pm_caps = PMC_CAP_SYSTEM; + pa.pm_class = PMC_CLASS_IBS; + pa.pm_mode = PMC_MODE_SC; + pa.pm_cpu = 0; + pa.pm_md.pm_ibs.ibs_type = IBS_PMC_OP; + + ATF_REQUIRE_ERRNO(EINVAL, hwpmc_call(PMC_OP_PMCALLOCATE, &pa) == -1); + require_exterr("IBS only supports sampling mode"); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, pmcallocate_invalid_mode); + ATF_TP_ADD_TC(tp, pmcallocate_invalid_cpu); + ATF_TP_ADD_TC(tp, pmcallocate_invalid_flags); + ATF_TP_ADD_TC(tp, pmcattach_system_mode); + ATF_TP_ADD_TC(tp, pmcattach_running_pmc); + ATF_TP_ADD_TC(tp, pmcrw_no_flags); + ATF_TP_ADD_TC(tp, pmcrw_write_running); + ATF_TP_ADD_TC(tp, amd_invalid_subclass); + ATF_TP_ADD_TC(tp, amd_invalid_config_bits); + ATF_TP_ADD_TC(tp, amd_invalid_df_config_bits); + ATF_TP_ADD_TC(tp, ibs_missing_system_capability); + ATF_TP_ADD_TC(tp, ibs_invalid_type); + ATF_TP_ADD_TC(tp, ibs_invalid_config_bits); + ATF_TP_ADD_TC(tp, ibs_nonsampling_mode); + + return (atf_no_error()); +}