Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F174508708
D57639.id188469.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D57639.id188469.diff
View Options
diff --git a/tools/regression/pmc/Makefile b/tools/regression/pmc/Makefile
--- a/tools/regression/pmc/Makefile
+++ b/tools/regression/pmc/Makefile
@@ -35,7 +35,7 @@
CXXFLAGS+= -O -g -Wall
# Kernel ABI tests (need hwpmc(4) loaded and root to run).
-KTESTS= pmc_group_test
+KTESTS= pmc_group_test pmc_mux_test
# Userland-only tests (no PMU access).
UTESTS=
@@ -51,6 +51,9 @@
pmc_group_test: ${.CURDIR}/pmc_group_test.c
${CC} ${CFLAGS} -o ${.TARGET} ${.ALLSRC} -lpmc
+pmc_mux_test: ${.CURDIR}/pmc_mux_test.c
+ ${CC} ${CFLAGS} -o ${.TARGET} ${.ALLSRC} -lpmc
+
# These are userland-only checks: parsers and pmcstat warning policy.
check: ${UTESTS}
@@ -58,6 +61,8 @@
check-root: ${KTESTS}
@echo "==> pmc_group_test"
./pmc_group_test
+ @echo "==> pmc_mux_test"
+ ./pmc_mux_test
clean:
rm -f ${ALL} *.o *.core
diff --git a/tools/regression/pmc/pmc_mux_test.c b/tools/regression/pmc/pmc_mux_test.c
new file mode 100644
--- /dev/null
+++ b/tools/regression/pmc/pmc_mux_test.c
@@ -0,0 +1,164 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Test rejection of single groups larger than hardware capacity.
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <errno.h>
+#include <pmc.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MAX_EVENTS 24
+
+static const char *events[MAX_EVENTS] = {
+ "instructions",
+ "unhalted-cycles",
+ "branches",
+ "branch-misses",
+ "cache-references",
+ "cache-misses",
+ "l1d-loads",
+ "l1d-load-misses",
+ "l2-cache-references",
+ "l2-cache-misses",
+ "dispatch-stalls",
+ "fp-retired",
+ "branches-retired",
+ "de-no-dispatch-per-slot",
+ "l2-pf-hit-l2",
+ "l2-pf-hit-l3",
+ "ls_alloc_mab_count",
+ "ls_not_halted_cyc",
+ "ls_dispatch.all",
+ "ls_mab_alloc.ls",
+ "ls_mab_alloc.hwpf",
+ "ls_mab_alloc.all",
+ "ls_int_taken",
+ "ls_stlf",
+};
+
+static int
+is_amd(void)
+{
+ char buf[64];
+ size_t s = sizeof(buf);
+
+ if (sysctlbyname("kern.hwpmc.cpuid", buf, &s, NULL, 0) != 0)
+ return (0);
+ return (strstr(buf, "AuthenticAMD") != NULL ||
+ strstr(buf, "HygonGenuine") != NULL);
+}
+
+/* Return the number of available core hardware counters. */
+static int
+probe_core_pmcs(void)
+{
+ pmc_id_t ids[64];
+ int n = 0;
+
+ while (n < (int)(sizeof(ids) / sizeof(ids[0]))) {
+ if (pmc_allocate("instructions", PMC_MODE_TC, 0,
+ PMC_CPU_ANY, &ids[n], 0) < 0)
+ break;
+ n++;
+ }
+ for (int i = 0; i < n; i++)
+ (void)pmc_release(ids[i]);
+ return (n);
+}
+
+int
+main(void)
+{
+ pmc_id_t ids[MAX_EVENTS];
+ uint32_t gid = 0;
+ int i, core, target, allocated, commit_errno, rc;
+
+ if (pmc_init() < 0)
+ err(1, "pmc_init");
+ if (!is_amd()) {
+ printf("SKIP: non-AMD CPU\n");
+ return (77);
+ }
+ core = probe_core_pmcs();
+ if (core < 2) {
+ printf("SKIP: probe found only %d core PMCs\n", core);
+ return (77);
+ }
+
+ /* Create a group with (core + 2) events. */
+ target = core + 2;
+ if (target > MAX_EVENTS) {
+ printf("SKIP: %d-counter CPU exceeds test pool (%d)\n",
+ core, MAX_EVENTS);
+ return (77);
+ }
+
+ if (pmc_group_create(&gid) < 0)
+ err(1, "pmc_group_create");
+
+ allocated = 0;
+ for (i = 0; i < MAX_EVENTS && allocated < target; i++) {
+ uint32_t flags = 0;
+
+ if (allocated == 0)
+ flags |= PMC_F_GROUP_MUX;
+ if (pmc_allocate_group(events[i], PMC_MODE_TC, flags,
+ PMC_CPU_ANY, &ids[allocated], 0) < 0) {
+ /* Skip the unsupported event. */
+ continue;
+ }
+ if (pmc_group_add(gid, ids[allocated], allocated == 0) < 0) {
+ (void)pmc_release(ids[allocated]);
+ continue;
+ }
+ allocated++;
+ }
+
+ if (allocated <= core) {
+ fprintf(stderr,
+ "SKIP: only %d events allocated, can't oversubscribe "
+ "a %d-counter core pool\n", allocated, core);
+ for (i = 0; i < allocated; i++)
+ (void)pmc_release(ids[i]);
+ return (77);
+ }
+
+ rc = pmc_group_commit(gid);
+ commit_errno = errno;
+ if (rc == 0)
+ (void)pmc_release(ids[0]);
+ else {
+ for (i = 0; i < allocated; i++)
+ (void)pmc_release(ids[i]);
+ }
+
+ /* A single group over hardware capacity must fail commit with ENOSPC. */
+ if (rc == 0) {
+ fprintf(stderr,
+ "FAIL: pmc_group_commit succeeded for %d events on "
+ "a %d-counter core pool; a single group must not be "
+ "split (within-group atomicity)\n", allocated, core);
+ return (1);
+ }
+ if (commit_errno != ENOSPC) {
+ fprintf(stderr,
+ "FAIL: expected ENOSPC from oversubscribed commit, "
+ "got errno=%d (%s)\n", commit_errno,
+ strerror(commit_errno));
+ return (1);
+ }
+
+ printf("oversubscribed single group rejected (events=%d "
+ "core_pool=%d errno=%d)\n", allocated, core, commit_errno);
+ printf("pmc_mux_test: OK\n");
+ return (0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 4, 7:30 PM (1 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40115301
Default Alt Text
D57639.id188469.diff (4 KB)
Attached To
Mode
D57639: tools/regression/pmc: hwpmc multiplex rejection test
Attached
Detach File
Event Timeline
Log In to Comment