{"id":2173986,"url":"http://patchwork.ozlabs.org/api/patches/2173986/?format=json","web_url":"http://patchwork.ozlabs.org/project/kvm-riscv/patch/20251213150848.149729-5-jamestiotio@gmail.com/","project":{"id":70,"url":"http://patchwork.ozlabs.org/api/projects/70/?format=json","name":"Linux KVM RISC-V","link_name":"kvm-riscv","list_id":"kvm-riscv.lists.infradead.org","list_email":"kvm-riscv@lists.infradead.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"http://lists.infradead.org/pipermail/kvm-riscv/","list_archive_url_format":"","commit_url_format":""},"msgid":"<20251213150848.149729-5-jamestiotio@gmail.com>","list_archive_url":null,"date":"2025-12-13T15:08:48","name":"[kvm-unit-tests,4/4] riscv: sbi: Add tests for PMU extension","commit_ref":null,"pull_url":null,"state":"handled-elsewhere","archived":false,"hash":"0a5f764640bcd9e6babfbf04704cd309af130b14","submitter":{"id":85990,"url":"http://patchwork.ozlabs.org/api/people/85990/?format=json","name":"James Raphael Tiovalen","email":"jamestiotio@gmail.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/kvm-riscv/patch/20251213150848.149729-5-jamestiotio@gmail.com/mbox/","series":[{"id":485289,"url":"http://patchwork.ozlabs.org/api/series/485289/?format=json","web_url":"http://patchwork.ozlabs.org/project/kvm-riscv/list/?series=485289","date":"2025-12-13T15:08:44","name":"riscv: sbi: Add support to test PMU extension","version":1,"mbox":"http://patchwork.ozlabs.org/series/485289/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2173986/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2173986/checks/","tags":{},"related":[],"headers":{"Return-Path":"\n <kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=lists.infradead.org header.i=@lists.infradead.org\n header.a=rsa-sha256 header.s=bombadil.20210309 header.b=xCW7kKcS;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=jOPMY7Ls;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.infradead.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n [IPv6:2607:7c80:54:3::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dT8qs0wlKz1xvn\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 14 Dec 2025 02:09:29 +1100 (AEDT)","from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1vURFN-00000001ihO-1IGq;\n\tSat, 13 Dec 2025 15:09:25 +0000","from mail-pl1-x632.google.com ([2607:f8b0:4864:20::632])\n\tby bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1vURFF-00000001ifQ-1vyW\n\tfor kvm-riscv@lists.infradead.org;\n\tSat, 13 Dec 2025 15:09:22 +0000","by mail-pl1-x632.google.com with SMTP id\n d9443c01a7336-299d40b0845so31454225ad.3\n        for <kvm-riscv@lists.infradead.org>;\n Sat, 13 Dec 2025 07:09:17 -0800 (PST)","from JRT-PC.. ([111.94.32.24])\n        by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-29eea016c6esm85494715ad.59.2025.12.13.07.09.14\n        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n        Sat, 13 Dec 2025 07:09:16 -0800 (PST)"],"DKIM-Signature":["v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20210309; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=QLQOhmMru0jX6o8emGTR3rPGo5186OuWoFdB9vPh9yo=; b=xCW7kKcSo79urV\n\ttL8FsN8PymgjhLiQL6HgEvl/3xxu4E13G1Ay/9+MUgRVUjcDsC3yLPutup1YDvvLZj9U0NRMlrumb\n\t/cQcz8Lc2zi2RwKkkwPTxUgQyeXo026fPRJ3bo4OlepMRkEBQoNcePG811Cw9aMHHl4xrEQB9+tPL\n\tmkNW8O+vHuALN1LuMs+NPGVcYULPb4yN4l6OY9IpeP2GCO3pIzie8h5Hmqt76j8wUi4JQ9MjhfWOt\n\tfzGjBxjyKXJwLavjEMLDSQA5kRNkhQqzbUZM3dzuueszlyPax+gH5y2Wv/g6N6EYh61q+AvpKUJKT\n\tplI2XMuJ7e/26Bqjl5iA==;","v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=gmail.com; s=20230601; t=1765638557; x=1766243357;\n darn=lists.infradead.org;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n         :message-id:reply-to;\n        bh=YHF+94AX9IsJfwresP4VoZ0BFogumn+V5OleWUNGOrE=;\n        b=jOPMY7LsdKu61DTEQEpjG3vNVhIO6zMCE06SpwzOD1iwBEETMUNq109NCN5kzCXT4L\n         3vXaI6wb4wzaQKHLLuWoIoraxvvRMN30XIm637NN9T67jugAOGrnxRGDJUHx2szzundR\n         I3u5eximc3bCzZHg3p2z+ygIJUuq5N4IAwOoxwbkxmF0Wm42Pp2jn9miZn6qstY+s2Fw\n         tGWIcClVItfKTGFgTZItlURHRRoEfU8B7CNZ1vpvWAkIDAAYswnfMsA3AgmJKcElpaXQ\n         mnPA2PuBcIe6qngwlcMkTxmyzPC5xBrcH6k/6M7P5iJzLse3HSiNIFtJghNzXko8ITVB\n         E/YA=="],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=1e100.net; s=20230601; t=1765638557; x=1766243357;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n         :to:cc:subject:date:message-id:reply-to;\n        bh=YHF+94AX9IsJfwresP4VoZ0BFogumn+V5OleWUNGOrE=;\n        b=UYeO/kcLPG9DVYf1lO3fC92cTz/P7CJzL2yWshjlLhLbb+qDprn8fa9ZZb4dsWdsUX\n         uOJTqKbIcpNMuIzQvSgB63avGFoCNo2eeiTKBcx+waMCFY/VanCU7ynxxpWSfChj6fBo\n         UqdSDDMOMYtdMCLmliji7DWcuSae7dYCKGZ8CsvCmcO/jTlGLrNrtj/Emmk4rf+Zbgyk\n         9UoFC7uBQpKpFjsJA8uf0P4e6/iz97BV3PPqAUp/g3ub58Alx7p7e7a6pYdxVN+2jqFx\n         Tr9m3YcRtrC7GolIZu5PEapqaU2HHCkiDiXrcOfoMFtmVBMXVLvAY94dRb/f3x8O0IOk\n         Rscw==","X-Forwarded-Encrypted":"i=1;\n AJvYcCXWU/02+i++lIjo4sZRI3juF5wgeOC3k1Hb/AhYP/ReJANd5aR30n/71U5HzEKONlWfVeIC1jpjWc0=@lists.infradead.org","X-Gm-Message-State":"AOJu0Yx3b3rcmqaIq1RioHNIuv7H8S0xKAWItymbLyC9t+a26JKAhPBc\n\tgFiWb7YLzhpyHO2PShA+Gn5qLJhk0USJKPkmgZDbFMYSaCSRQ4m4inqy","X-Gm-Gg":"AY/fxX783kNCe5yKd0qA3cc43NoGJy7myioPBbhTxG5Cd0TASe1p/E7MM6Up81GfO6w\n\t8zZ/kK3Q1lLhfAsqTfn3g/U/nKKY8NXrUbQjmqTSZHRALpYrWG5c71mqmRgGMJARwZEOtYKuhaH\n\tTDIwC9q0Ze8mK3jDO0Yhg1oc7aNQhiehq47N/tQy/7KCUJVyujkLQiqLDvbiJFrxbftXDxFuSyj\n\tCQ/VrQT6o4olITiI9HuPnTFoV6gD0UTDLhHgbxPk9F0tPUPuXYpa8Ilp8FfaC71B5U7kjMs77CX\n\t8iq9HQINsyPvN0H5RQ1J7aUnit85Kdw4/pGzY3MleiaUcCrtrACof2QKd88HxI6XCYFSgM44oNd\n\t/Lb3plzBkmXLHUxLjg1S3MLIT+N5T2iwM7QeCSnkY4YrGeXN/Kv9n2FrMoy2f9zpc+OAndmaJpe\n\trPdia+iorTHkTNFdvM","X-Google-Smtp-Source":"\n AGHT+IH5SF9o/7ISeAlP3eC1if6rKolBgvqgtC65K6/yldfspYSFfs0X7lNwOIXNJqG91qWeWDYTkg==","X-Received":"by 2002:a17:903:2b10:b0:2a0:9ecc:694a with SMTP id\n d9443c01a7336-2a09ecc6b3cmr14888095ad.37.1765638556521;\n        Sat, 13 Dec 2025 07:09:16 -0800 (PST)","From":"James Raphael Tiovalen <jamestiotio@gmail.com>","To":"kvm@vger.kernel.org,\n\tkvm-riscv@lists.infradead.org","Cc":"andrew.jones@linux.dev,\n\tatishp@rivosinc.com,\n\tJames Raphael Tiovalen <jamestiotio@gmail.com>","Subject":"[kvm-unit-tests PATCH 4/4] riscv: sbi: Add tests for PMU extension","Date":"Sat, 13 Dec 2025 23:08:48 +0800","Message-ID":"<20251213150848.149729-5-jamestiotio@gmail.com>","X-Mailer":"git-send-email 2.43.0","In-Reply-To":"<20251213150848.149729-1-jamestiotio@gmail.com>","References":"<20251213150848.149729-1-jamestiotio@gmail.com>","MIME-Version":"1.0","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20251213_070919_338360_32CFF63C ","X-CRM114-Status":"GOOD (  19.67  )","X-Spam-Score":"-2.1 (--)","X-Spam-Report":"Spam detection software,\n running on the system \"bombadil.infradead.org\",\n has NOT identified this incoming email as spam.  The original\n message has been attached to this so you can view it or label\n similar future email.  If you have any questions, see\n the administrator of that system for details.\n Content preview:  Add the actual tests for the SBI PMU extension. Functions\n   related to shared memory (FID #7 and #8) are untested for now.\n Signed-off-by:\n    James Raphael Tiovalen --- riscv/Makefile | 1 + riscv/sbi-tests.h | 1 +\n riscv/sbi-pmu.c\n    | 461 ++++++++++++++++++++++++++++++++++++++++++++++ riscv/sbi.c | 2 + 4\n   files changed, 465 ins [...]\n Content analysis details:   (-2.1 points, 5.0 required)\n  pts rule name              description\n ---- ----------------------\n --------------------------------------------------\n -0.0 RCVD_IN_DNSWL_NONE     RBL: Sender listed at https://www.dnswl.org/, no\n                             trust\n                             [2607:f8b0:4864:20:0:0:0:632 listed in]\n                             [list.dnswl.org]\n -0.0 SPF_PASS               SPF: sender matches SPF record\n  0.0 SPF_HELO_NONE          SPF: HELO does not publish an SPF Record\n -0.1 DKIM_VALID_AU          Message has a valid DKIM or DK signature from\n author's\n                             domain\n -0.1 DKIM_VALID             Message has at least one valid DKIM or DK\n signature\n  0.1 DKIM_SIGNED            Message has a DKIM or DK signature,\n not necessarily valid\n -0.1 DKIM_VALID_EF          Message has a valid DKIM or DK signature from\n                             envelope-from domain\n -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n                             [score: 0.0000]\n  0.0 FREEMAIL_FROM          Sender email is commonly abused enduser mail\n provider\n                             [jamestiotio(at)gmail.com]","X-BeenThere":"kvm-riscv@lists.infradead.org","X-Mailman-Version":"2.1.34","Precedence":"list","List-Id":"<kvm-riscv.lists.infradead.org>","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/kvm-riscv>,\n <mailto:kvm-riscv-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/kvm-riscv/>","List-Post":"<mailto:kvm-riscv@lists.infradead.org>","List-Help":"<mailto:kvm-riscv-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/kvm-riscv>,\n <mailto:kvm-riscv-request@lists.infradead.org?subject=subscribe>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"\"kvm-riscv\" <kvm-riscv-bounces@lists.infradead.org>","Errors-To":"kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org"},"content":"Add the actual tests for the SBI PMU extension. Functions related to\nshared memory (FID #7 and #8) are untested for now.\n\nSigned-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>\n---\n riscv/Makefile    |   1 +\n riscv/sbi-tests.h |   1 +\n riscv/sbi-pmu.c   | 461 ++++++++++++++++++++++++++++++++++++++++++++++\n riscv/sbi.c       |   2 +\n 4 files changed, 465 insertions(+)\n create mode 100644 riscv/sbi-pmu.c","diff":"diff --git a/riscv/Makefile b/riscv/Makefile\nindex c0dd5465..75a108c1 100644\n--- a/riscv/Makefile\n+++ b/riscv/Makefile\n@@ -21,6 +21,7 @@ all: $(tests)\n sbi-deps += $(TEST_DIR)/sbi-asm.o\n sbi-deps += $(TEST_DIR)/sbi-dbtr.o\n sbi-deps += $(TEST_DIR)/sbi-fwft.o\n+sbi-deps += $(TEST_DIR)/sbi-pmu.o\n sbi-deps += $(TEST_DIR)/sbi-sse.o\n \n all_deps += $(sbi-deps)\ndiff --git a/riscv/sbi-tests.h b/riscv/sbi-tests.h\nindex c1ebf016..509ec547 100644\n--- a/riscv/sbi-tests.h\n+++ b/riscv/sbi-tests.h\n@@ -99,6 +99,7 @@ static inline bool env_enabled(const char *env)\n \n void split_phys_addr(phys_addr_t paddr, unsigned long *hi, unsigned long *lo);\n void sbi_bad_fid(int ext);\n+void check_pmu(void);\n void check_sse(void);\n void check_dbtr(void);\n \ndiff --git a/riscv/sbi-pmu.c b/riscv/sbi-pmu.c\nnew file mode 100644\nindex 00000000..5d2e034a\n--- /dev/null\n+++ b/riscv/sbi-pmu.c\n@@ -0,0 +1,461 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/*\n+ * SBI PMU test suite\n+ *\n+ * Copyright (C) 2025, James Raphael Tiovalen <jamestiotio@gmail.com>\n+ */\n+#include <alloc.h>\n+#include <alloc_page.h>\n+#include <bitops.h>\n+#include <cpumask.h>\n+#include <libcflat.h>\n+#include <on-cpus.h>\n+#include <stdlib.h>\n+\n+#include <asm/csr.h>\n+#include <asm/io.h>\n+#include <asm/page.h>\n+#include <asm/sbi.h>\n+#include <asm/pmu.h>\n+\n+#include \"sbi-tests.h\"\n+\n+#define SBI_PMU_COUNTER_TEST_INIT_VALUE 0x7FFFFFFF\n+\n+struct sbi_ext_pmu_ctr_csr_map {\n+\tbool mapped;\n+\tbool is_fw_ctr;\n+\tunsigned long ctr_idx;\n+\tunsigned long csr;\n+};\n+\n+static unsigned long number_of_counters;\n+static struct sbi_ext_pmu_ctr_csr_map *sbi_ext_pmu_ctr_csr_map;\n+\n+static unsigned long get_counter_idx_from_csr(unsigned long csr);\n+struct sbi_ext_pmu_test_ctr sbi_ext_pmu_get_candidate_fw_counter_for_test(void);\n+uint64_t sbi_ext_pmu_read_fw_counter(unsigned long ctr_idx);\n+\n+static unsigned long get_counter_idx_from_csr(unsigned long csr)\n+{\n+\tfor (unsigned long i = 0; i < number_of_counters; i++) {\n+\t\tif (sbi_ext_pmu_ctr_csr_map[i].mapped &&\n+\t\t    sbi_ext_pmu_ctr_csr_map[i].csr == csr) {\n+\t\t\treturn sbi_ext_pmu_ctr_csr_map[i].ctr_idx;\n+\t\t}\n+\t}\n+\n+\tassert_msg(false, \"CSR %lx not found in the map\", csr);\n+}\n+\n+struct sbi_ext_pmu_test_ctr sbi_ext_pmu_get_candidate_fw_counter_for_test(void)\n+{\n+\tstruct sbi_ext_pmu_test_ctr test_ctr = {0};\n+\n+\tif (!sbi_probe(SBI_EXT_TIME)) {\n+\t\ttest_ctr.ctr_idx = -1;\n+\t\treturn test_ctr;\n+\t}\n+\n+\tset_cidx_type(test_ctr.eid, SBI_EXT_PMU_EVENT_FW);\n+\tset_cidx_code(test_ctr.eid, SBI_EXT_PMU_FW_SET_TIMER);\n+\n+\t/* Since any firmware counter can be used for testing, return the first one found */\n+\tfor (unsigned long i = 0; i < number_of_counters; i++) {\n+\t\tif (sbi_ext_pmu_ctr_csr_map[i].mapped && sbi_ext_pmu_ctr_csr_map[i].is_fw_ctr) {\n+\t\t\ttest_ctr.ctr_idx = sbi_ext_pmu_ctr_csr_map[i].ctr_idx;\n+\t\t\treturn test_ctr;\n+\t\t}\n+\t}\n+\n+\ttest_ctr.ctr_idx = -1;\n+\treturn test_ctr;\n+}\n+\n+uint64_t sbi_ext_pmu_read_fw_counter(unsigned long ctr_idx)\n+{\n+\tstruct sbiret ret;\n+\tuint64_t ctr_val = 0;\n+\n+\tret = sbi_pmu_counter_fw_read(ctr_idx);\n+\treport(ret.error == SBI_SUCCESS,\n+\t       \"expected to read lower bits of firmware counter %ld successfully, got %ld\", ctr_idx, ret.error);\n+\n+\tctr_val = ret.value;\n+\n+\tret = sbi_pmu_counter_fw_read_hi(ctr_idx);\n+\treport(ret.error == SBI_SUCCESS,\n+\t       \"expected to read upper bits of firmware counter %ld successfully, got %ld\", ctr_idx, ret.error);\n+\n+\tctr_val += ((uint64_t)ret.value << 32);\n+\n+\treturn ctr_val;\n+}\n+\n+void check_pmu(void)\n+{\n+\tstruct sbiret ret;\n+\tunsigned long valid_counter_info = 0, num_of_hw_counters = 0;\n+\tuint64_t cycle_count, instret_count, test_counter_value;\n+\tbool timer_counter_found = false;\n+\tunion sbi_ext_pmu_ctr_info info;\n+\tunsigned long test_eid = 0, set_timer_count = 0;\n+\tint test_counter_idx;\n+\tstruct sbi_ext_pmu_test_ctr test_ctr = {0};\n+\n+\treport_prefix_push(\"pmu\");\n+\n+\tif (!sbi_probe(SBI_EXT_PMU)) {\n+\t\treport_skip(\"PMU extension unavailable\");\n+\t\treport_prefix_pop();\n+\t\treturn;\n+\t}\n+\n+\tsbi_bad_fid(SBI_EXT_PMU);\n+\n+\treport_prefix_push(\"pmu_num_counters\");\n+\n+\tret = sbi_pmu_num_counters();\n+\tif (ret.error) {\n+\t\treport_fail(\"failed to get number of counters (error=%ld)\", ret.error);\n+\t\treport_prefix_popn(2);\n+\t\treturn;\n+\t}\n+\tnumber_of_counters = ret.value;\n+\n+\t/* CSR_CYCLE, CSR_TIME, and CSR_INSTRET are mandatory counters */\n+\tif (number_of_counters < 3) {\n+\t\treport_fail(\"number of counters is %ld, expected at least 3\", number_of_counters);\n+\t\treport_prefix_popn(2);\n+\t\treturn;\n+\t}\n+\n+\treport_info(\"number of counters is %ld\", number_of_counters);\n+\n+\treport_prefix_pop();\n+\n+\treport_prefix_push(\"sbi_pmu_counter_get_info\");\n+\n+\tfdt_pmu_setup();\n+\n+\tsbi_ext_pmu_ctr_csr_map = calloc(number_of_counters,\n+\t\t\t\t\t    sizeof(struct sbi_ext_pmu_ctr_csr_map));\n+\n+\tfor (unsigned long i = 0; i < number_of_counters; i++) {\n+\t\tsbi_ext_pmu_ctr_csr_map[i].mapped = false;\n+\t\tsbi_ext_pmu_ctr_csr_map[i].is_fw_ctr = false;\n+\t\tsbi_ext_pmu_ctr_csr_map[i].ctr_idx = 0;\n+\t\tsbi_ext_pmu_ctr_csr_map[i].csr = 0;\n+\t}\n+\n+\tfor (unsigned long i = 0; i < number_of_counters; i++) {\n+\t\tret = sbi_pmu_counter_get_info(i);\n+\n+\t\tif (ret.error == SBI_ERR_INVALID_PARAM && !timer_counter_found) {\n+\t\t\t/* Assume that this is the CSR_TIME counter and skip it */\n+\t\t\ttimer_counter_found = true;\n+\t\t\tsbi_ext_pmu_ctr_csr_map[i].ctr_idx = i;\n+\t\t\tsbi_ext_pmu_ctr_csr_map[i].csr = CSR_TIME;\n+\t\t\tvalid_counter_info++;\n+\t\t\treport_info(\"skipping CSR_TIME counter with index %ld\", i);\n+\t\t\tcontinue;\n+\t\t} else if (ret.error) {\n+\t\t\tfree(sbi_ext_pmu_ctr_csr_map);\n+\t\t\tfdt_pmu_free();\n+\t\t\treport_fail(\"failed to get counter info (error=%ld)\", ret.error);\n+\t\t\treport_prefix_popn(2);\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tinfo = *(union sbi_ext_pmu_ctr_info *)&ret.value;\n+\n+\t\tif (info.type == SBI_EXT_PMU_CTR_TYPE_HW) {\n+\t\t\tsbi_ext_pmu_ctr_csr_map[i].mapped = true;\n+\t\t\tsbi_ext_pmu_ctr_csr_map[i].ctr_idx = i;\n+\t\t\tsbi_ext_pmu_ctr_csr_map[i].csr = info.csr;\n+\n+\t\t\tif ((info.csr == CSR_CYCLE) || (info.csr == CSR_INSTRET))\n+\t\t\t\tvalid_counter_info += info.width == 63;\n+\t\t\telse\n+\t\t\t\tvalid_counter_info++;\n+\n+\t\t\tnum_of_hw_counters++;\n+\t\t} else if (info.type == SBI_EXT_PMU_CTR_TYPE_FW) {\n+\t\t\tsbi_ext_pmu_ctr_csr_map[i].mapped = true;\n+\t\t\tsbi_ext_pmu_ctr_csr_map[i].is_fw_ctr = true;\n+\t\t\tsbi_ext_pmu_ctr_csr_map[i].ctr_idx = i;\n+\t\t\tvalid_counter_info++;\n+\t\t} else {\n+\t\t\tfree(sbi_ext_pmu_ctr_csr_map);\n+\t\t\tfdt_pmu_free();\n+\t\t\treport_fail(\"unknown counter type %d\", info.type);\n+\t\t\treport_prefix_popn(2);\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\n+\treport(valid_counter_info == number_of_counters,\n+\t       \"number of counters with valid info is %ld\", valid_counter_info);\n+\n+\tret = sbi_pmu_counter_get_info(number_of_counters);\n+\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t       \"expected %d when counter_idx == num_counters, got %ld\", SBI_ERR_INVALID_PARAM, ret.error);\n+\n+\treport_prefix_pop();\n+\n+\treport_prefix_push(\"sbi_pmu_counter_config_matching\");\n+\n+\tcycle_count = pmu_get_cycles();\n+\tinstret_count = pmu_get_instret();\n+\n+\tset_cidx_type(test_eid, SBI_EXT_PMU_EVENT_HW_GENERAL);\n+\tset_cidx_code(test_eid, SBI_EXT_PMU_HW_CPU_CYCLES);\n+\tret = sbi_pmu_counter_config_matching(get_counter_idx_from_csr(CSR_CYCLE),\n+\t\t\t\t\t      1,\n+\t\t\t\t\t      SBI_EXT_PMU_CFG_FLAG_CLEAR_VALUE,\n+\t\t\t\t\t      test_eid,\n+\t\t\t\t\t      0);\n+\n+\tif (ret.error) {\n+\t\tfree(sbi_ext_pmu_ctr_csr_map);\n+\t\tfdt_pmu_free();\n+\t\treport_fail(\"failed to configure counter (error=%ld)\", ret.error);\n+\t\treport_prefix_popn(2);\n+\t\treturn;\n+\t}\n+\n+\ttest_counter_value = pmu_get_cycles();\n+\n+\treport(test_counter_value < cycle_count,\n+\t       \"expected cycle count to reset (%ld < %ld)\", test_counter_value, cycle_count);\n+\n+\tset_cidx_code(test_eid, SBI_EXT_PMU_HW_INSTRUCTIONS);\n+\tret = sbi_pmu_counter_config_matching(get_counter_idx_from_csr(CSR_INSTRET),\n+\t\t\t\t\t      1,\n+\t\t\t\t\t      SBI_EXT_PMU_CFG_FLAG_CLEAR_VALUE,\n+\t\t\t\t\t      test_eid,\n+\t\t\t\t\t      0);\n+\n+\tif (ret.error) {\n+\t\tfree(sbi_ext_pmu_ctr_csr_map);\n+\t\tfdt_pmu_free();\n+\t\treport_fail(\"failed to configure counter (error=%ld)\", ret.error);\n+\t\treport_prefix_popn(2);\n+\t\treturn;\n+\t}\n+\n+\ttest_counter_value = pmu_get_instret();\n+\n+\treport(test_counter_value < instret_count,\n+\t       \"expected instret count to reset (%ld < %ld)\", test_counter_value, instret_count);\n+\n+\tset_cidx_code(test_eid, SBI_EXT_PMU_HW_CPU_CYCLES);\n+\ttest_counter_idx = sbi_ext_pmu_get_first_counter_for_hw_event(test_eid);\n+\n+\treport_info(\"first counter for test hw event %ld is %d\", test_eid, test_counter_idx);\n+\n+\tif (test_counter_idx <= 0) {\n+\t\treport_skip(\"failed to get first counter for test hw event\");\n+\t} else {\n+\t\ttest_counter_value = pmu_get_cycles();\n+\t\tret = sbi_pmu_counter_config_matching(test_counter_idx, 0, SBI_EXT_PMU_CFG_FLAG_CLEAR_VALUE,\n+\t\t\t\t\t\t      test_eid, 0);\n+\t\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t\t       \"expected %d when counter_idx_mask == 0, got %ld\", SBI_ERR_INVALID_PARAM, ret.error);\n+\t\treport(pmu_get_cycles() > test_counter_value,\n+\t\t       \"expected cycle counter to be unaffected when configuring counter %d\", test_counter_idx);\n+\t}\n+\n+\ttest_ctr = sbi_ext_pmu_get_candidate_hw_counter_for_test();\n+\ttest_counter_idx = test_ctr.ctr_idx;\n+\ttest_eid = test_ctr.eid;\n+\n+\treport_info(\"testing hardware counter %d with event %ld\", test_counter_idx, test_eid);\n+\n+\tret = sbi_pmu_counter_config_matching(test_counter_idx, 1,\n+\t\t\t\t\t      SBI_EXT_PMU_CFG_FLAG_SKIP_MATCH,\n+\t\t\t\t\t      test_eid, 0);\n+\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t       \"expected %d when skipping match before configuring counter, got %ld\",\n+\t       SBI_ERR_INVALID_PARAM, ret.error);\n+\n+\tret = sbi_pmu_counter_config_matching(test_counter_idx, 1,\n+\t\t\t\t\t      SBI_EXT_PMU_CFG_FLAG_CLEAR_VALUE | SBI_EXT_PMU_CFG_FLAG_AUTO_START,\n+\t\t\t\t\t      test_eid, 0);\n+\tif (ret.error) {\n+\t\tfree(sbi_ext_pmu_ctr_csr_map);\n+\t\tfdt_pmu_free();\n+\t\treport_fail(\"failed to configure counter (error=%ld)\", ret.error);\n+\t\treport_prefix_popn(2);\n+\t\treturn;\n+\t}\n+\treport(ret.value == test_counter_idx,\n+\t       \"expected counter %d to be configured (%ld == %d)\", test_counter_idx, ret.value, test_counter_idx);\n+\n+\ttest_counter_value = pmu_get_counter(sbi_ext_pmu_ctr_csr_map[test_counter_idx].csr);\n+\n+\treport(test_counter_value > 0,\n+\t       \"expected counter %d to auto-start (%ld > 0)\",\n+\t       test_counter_idx,\n+\t       test_counter_value);\n+\n+\ttest_eid = sbi_ext_pmu_get_first_unsupported_hw_event(test_counter_idx);\n+\tret = sbi_pmu_counter_config_matching(test_counter_idx, 1,\n+\t\t\t\t\t      SBI_EXT_PMU_CFG_FLAG_CLEAR_VALUE | SBI_EXT_PMU_CFG_FLAG_AUTO_START,\n+\t\t\t\t\t      test_eid, 0);\n+\treport(ret.error == SBI_ERR_NOT_SUPPORTED,\n+\t       \"expected counter %d to be unable to monitor event %ld, got %ld\",\n+\t       test_counter_idx, test_eid, ret.error);\n+\n+\ttest_eid = test_ctr.eid;\n+\n+\treport_prefix_pop();\n+\n+\treport_prefix_push(\"sbi_pmu_counter_start\");\n+\n+\tret = sbi_pmu_counter_start(test_counter_idx, 0, 0, 0);\n+\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t       \"expected %d when counter_idx_mask == 0, got %ld\", SBI_ERR_INVALID_PARAM, ret.error);\n+\n+\tret = sbi_pmu_counter_start(test_counter_idx, 1, 0, 0);\n+\treport(ret.error == SBI_ERR_ALREADY_STARTED,\n+\t       \"expected counter %d to be already started, got %ld\", test_counter_idx, ret.error);\n+\n+\treport_prefix_pop();\n+\n+\treport_prefix_push(\"sbi_pmu_counter_stop\");\n+\n+\tret = sbi_pmu_counter_stop(test_counter_idx, 0, 0);\n+\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t       \"expected %d when counter_idx_mask == 0, got %ld\", SBI_ERR_INVALID_PARAM, ret.error);\n+\n+\tret = sbi_pmu_counter_stop(test_counter_idx, 1, 0);\n+\treport(ret.error == SBI_SUCCESS,\n+\t       \"expected counter %d to be stopped, got %ld\", test_counter_idx, ret.error);\n+\n+\tret = sbi_pmu_counter_stop(test_counter_idx, 1, 0);\n+\treport(ret.error == SBI_ERR_ALREADY_STOPPED,\n+\t       \"expected counter %d to be already stopped, got %ld\", test_counter_idx, ret.error);\n+\n+\treport_prefix_pop();\n+\n+\treport_prefix_push(\"sbi_pmu_counter_start\");\n+\n+\tret = sbi_pmu_counter_start(test_counter_idx, 1, SBI_EXT_PMU_START_SET_INIT_VALUE,\n+\t\t\t\t    SBI_PMU_COUNTER_TEST_INIT_VALUE);\n+\treport(ret.error == SBI_SUCCESS,\n+\t       \"expected counter %d to be started with initial value, got %ld\", test_counter_idx, ret.error);\n+\n+\ttest_counter_value = pmu_get_counter(sbi_ext_pmu_ctr_csr_map[test_counter_idx].csr);\n+\treport(test_counter_value > SBI_PMU_COUNTER_TEST_INIT_VALUE,\n+\t       \"expected counter %d to start with initial value (%ld > %d)\",\n+\t       test_counter_idx, test_counter_value, SBI_PMU_COUNTER_TEST_INIT_VALUE);\n+\n+\treport_prefix_pop();\n+\n+\treport_prefix_push(\"sbi_pmu_counter_stop\");\n+\n+\tret = sbi_pmu_counter_stop(test_counter_idx, 1, 0);\n+\treport(ret.error == SBI_SUCCESS,\n+\t       \"expected counter %d to be stopped, got %ld\", test_counter_idx, ret.error);\n+\n+\treport_prefix_pop();\n+\n+\treport_prefix_push(\"sbi_pmu_counter_fw_read\");\n+\n+\tret = sbi_pmu_counter_fw_read(number_of_counters);\n+\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t       \"expected %d when counter_idx == num_counters, got %ld\", SBI_ERR_INVALID_PARAM, ret.error);\n+\n+\tret = sbi_pmu_counter_fw_read_hi(number_of_counters);\n+\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t       \"expected %d when counter_idx == num_counters, got %ld\", SBI_ERR_INVALID_PARAM, ret.error);\n+\n+\ttest_ctr = sbi_ext_pmu_get_candidate_fw_counter_for_test();\n+\ttest_counter_idx = test_ctr.ctr_idx;\n+\ttest_eid = test_ctr.eid;\n+\n+\tif (test_counter_idx < 0) {\n+\t\tfree(sbi_ext_pmu_ctr_csr_map);\n+\t\tfdt_pmu_free();\n+\t\treport_skip(\"no firmware counters available for testing\");\n+\t\treport_prefix_popn(2);\n+\t\treturn;\n+\t}\n+\n+\treport_info(\"testing firmware counter %d with event 0x%lx\", test_counter_idx, test_eid);\n+\n+\tret = sbi_pmu_counter_config_matching(test_counter_idx, 1,\n+\t\t\t\t\t      SBI_EXT_PMU_CFG_FLAG_CLEAR_VALUE | SBI_EXT_PMU_CFG_FLAG_AUTO_START,\n+\t\t\t\t\t      test_eid, 0);\n+\tif (ret.error) {\n+\t\tfree(sbi_ext_pmu_ctr_csr_map);\n+\t\tfdt_pmu_free();\n+\t\treport_fail(\"failed to configure counter (error=%ld)\", ret.error);\n+\t\treport_prefix_popn(2);\n+\t\treturn;\n+\t}\n+\treport(ret.value == test_counter_idx,\n+\t       \"expected counter %d to be configured (%ld == %d)\", test_counter_idx, ret.value, test_counter_idx);\n+\n+\ttest_counter_value = sbi_ext_pmu_read_fw_counter(test_counter_idx);\n+\n+\treport(test_counter_value == set_timer_count,\n+\t       \"expected counter %d to be cleared (%ld == %ld)\",\n+\t       test_counter_idx,\n+\t       test_counter_value,\n+\t       set_timer_count);\n+\n+\tret = sbi_pmu_counter_start(test_counter_idx, 0, 0, 0);\n+\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t       \"expected %d when counter_idx_mask == 0, got %ld\", SBI_ERR_INVALID_PARAM, ret.error);\n+\n+\tret = sbi_pmu_counter_start(test_counter_idx, 1, 0, 0);\n+\treport(ret.error == SBI_ERR_ALREADY_STARTED,\n+\t       \"expected counter %d to be already started, got %ld\", test_counter_idx, ret.error);\n+\n+\tsbi_set_timer(0);\n+\tset_timer_count++;\n+\ttest_counter_value = sbi_ext_pmu_read_fw_counter(test_counter_idx);\n+\n+\treport(test_counter_value == set_timer_count,\n+\t       \"expected counter %d to have incremented (%ld == %ld)\",\n+\t       test_counter_idx,\n+\t       test_counter_value,\n+\t       set_timer_count);\n+\n+\tsbi_set_timer(ULONG_MAX);\n+\tset_timer_count++;\n+\ttest_counter_value = sbi_ext_pmu_read_fw_counter(test_counter_idx);\n+\n+\treport(test_counter_value == set_timer_count,\n+\t       \"expected counter %d to have incremented (%ld == %ld)\",\n+\t       test_counter_idx,\n+\t       test_counter_value,\n+\t       set_timer_count);\n+\n+\tret = sbi_pmu_counter_stop(test_counter_idx, 0, 0);\n+\treport(ret.error == SBI_ERR_INVALID_PARAM,\n+\t       \"expected %d when counter_idx_mask == 0, got %ld\", SBI_ERR_INVALID_PARAM, ret.error);\n+\n+\tret = sbi_pmu_counter_stop(test_counter_idx, 1, 0);\n+\treport(ret.error == SBI_SUCCESS,\n+\t       \"expected counter %d to be stopped, got %ld\", test_counter_idx, ret.error);\n+\n+\tret = sbi_pmu_counter_stop(test_counter_idx, 1, 0);\n+\treport(ret.error == SBI_ERR_ALREADY_STOPPED,\n+\t       \"expected counter %d to be already stopped, got %ld\", test_counter_idx, ret.error);\n+\n+\tsbi_set_timer(ULONG_MAX);\n+\ttest_counter_value = sbi_ext_pmu_read_fw_counter(test_counter_idx);\n+\n+\treport(test_counter_value == set_timer_count,\n+\t       \"expected counter %d to be unchanged after stop (%ld == %ld)\",\n+\t       test_counter_idx,\n+\t       test_counter_value,\n+\t       set_timer_count);\n+\n+\tfree(sbi_ext_pmu_ctr_csr_map);\n+\tfdt_pmu_free();\n+\treport_prefix_popn(2);\n+}\ndiff --git a/riscv/sbi.c b/riscv/sbi.c\nindex 3b8aadce..fdb6a38a 100644\n--- a/riscv/sbi.c\n+++ b/riscv/sbi.c\n@@ -32,6 +32,7 @@\n \n #define\tHIGH_ADDR_BOUNDARY\t((phys_addr_t)1 << 32)\n \n+void check_pmu(void);\n void check_sse(void);\n void check_fwft(void);\n \n@@ -1557,6 +1558,7 @@ int main(int argc, char **argv)\n \tcheck_time();\n \tcheck_ipi();\n \tcheck_hsm();\n+\tcheck_pmu();\n \tcheck_dbcn();\n \tcheck_susp();\n \tcheck_sse();\n","prefixes":["kvm-unit-tests","4/4"]}