Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177430779
D61374.1794362440.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
5 KB
Referenced Files
None
Subscribers
None
D61374.1794362440.diff
View Options
diff --git a/share/man/man4/hwpmc.4 b/share/man/man4/hwpmc.4
--- a/share/man/man4/hwpmc.4
+++ b/share/man/man4/hwpmc.4
@@ -503,6 +503,13 @@
.It Va kern.hwpmc.nsamples Pq integer, read-only
The number of entries in the per-CPU ring buffer used during sampling.
The default is 256.
+.It Va kern.hwpmc.throttle_pconly Pq integer, read-write
+If set to non-zero, a PMC that reached
+.Va kern.hwpmc.max_sample_rate
+in the previous clock tick records only the program counter.
+The driver does not walk the call stack for these samples.
+This decreases the cost of each interrupt while the sample rate is high.
+The default is 1.
.It Va security.bsd.unprivileged_syspmcs Pq boolean, read-write
If set to non-zero, allow unprivileged processes to allocate system-wide
PMCs.
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -340,6 +340,12 @@
pmc_max_sample_rate_sysctl_handler, "IU",
"maximum samples per second for one PMC on one CPU (0: no limit)");
+/* Skip callchains after a rate stop. */
+static int pmc_throttle_pconly = 1;
+SYSCTL_INT(_kern_hwpmc, OID_AUTO, throttle_pconly, CTLFLAG_RWTUN,
+ &pmc_throttle_pconly, 0,
+ "record only the PC after a tick at the sample rate limit");
+
/* Interrupt CPU budget. Zero and 100 disable it. */
static u_int pmc_cpu_time_max_percent = PMC_CPU_TIME_MAX_PERCENT;
static u_int pmc_intr_allowed_ns; /* 0: limit disabled */
@@ -5108,8 +5114,8 @@
ps->ps_flags = inuserspace ? PMC_CC_F_USERSPACE : 0;
ps->ps_nsamples_actual = 0;
- callchaindepth = (pm->pm_flags & PMC_F_CALLCHAIN) != 0 ?
- pmc_callchaindepth : 1;
+ callchaindepth = (pm->pm_flags & PMC_F_CALLCHAIN) != 0 &&
+ pm->pm_pcpu_state[cpu].pps_pconly == 0 ? pmc_callchaindepth : 1;
MPASS(ps->ps_pc != NULL);
@@ -5122,7 +5128,9 @@
}
if (callchaindepth == 1) {
+ /* Keep multipart data before the PC. */
ps->ps_pc[ps->ps_nsamples_actual] = PMC_TRAPFRAME_TO_PC(tf);
+ callchaindepth = ps->ps_nsamples_actual + 1;
} else {
/*
* Kernel stack traversals can be done immediately, while we
@@ -5181,6 +5189,10 @@
pps = &pm->pm_pcpu_state[curcpu];
seq = DPCPU_GET(pmc_tick_seq);
if (pps->pps_intr_tick != seq) {
+ /* Skip stack walks after a rate stop. */
+ pps->pps_pconly = pmc_throttle_pconly != 0 &&
+ pps->pps_intr_tick == seq - 1 &&
+ pps->pps_intr_count > limit;
pps->pps_intr_tick = seq;
pps->pps_intr_count = 0;
}
@@ -5191,6 +5203,8 @@
DPCPU_SET(pmc_sampled, 1);
return (EBUSY);
}
+ } else {
+ pm->pm_pcpu_state[curcpu].pps_pconly = 0;
}
td = curthread;
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -756,6 +756,7 @@
u_int pps_lost; /* Drop flags and count. */
uint8_t pps_stalled;
uint8_t pps_cpustate;
+ uint8_t pps_pconly; /* PC only. */
} __aligned(CACHE_LINE_SIZE);
struct pmc {
LIST_HEAD(,pmc_target) pm_targets; /* list of target processes */
diff --git a/tests/sys/pmc/pmc_throttle_test.c b/tests/sys/pmc/pmc_throttle_test.c
--- a/tests/sys/pmc/pmc_throttle_test.c
+++ b/tests/sys/pmc/pmc_throttle_test.c
@@ -637,6 +637,78 @@
sysctls_restore();
}
+/* Keep IBS data in PC-only samples. */
+ATF_TC_WITH_CLEANUP(pconly_ibs);
+ATF_TC_HEAD(pconly_ibs, tc)
+{
+ atf_tc_set_md_var(tc, "require.user", "root");
+ atf_tc_set_md_var(tc, "timeout", "30");
+}
+ATF_TC_BODY(pconly_ibs, tc)
+{
+ struct pmclog_ev ev;
+ uint64_t bad, nrec, throttled;
+ pmc_id_t id;
+ uint8_t *hdr;
+ void *parser;
+ u_int i, len;
+ int fd;
+
+ if (hwpmc_get("throttle_pconly") == 0)
+ atf_tc_skip("kern.hwpmc.throttle_pconly is 0");
+ (void)throttle_setup(10);
+ test_event = "ibs-op";
+ test_flags = PMC_F_CALLCHAIN;
+ test_period = 65536;
+
+ (void)measure_log(&throttled, "ibs.log", &id);
+
+ sysctls_restore();
+
+ fd = open("ibs.log", O_RDONLY);
+ ATF_REQUIRE(fd >= 0);
+ parser = pmclog_open(fd);
+ ATF_REQUIRE(parser != NULL);
+ bad = nrec = 0;
+ while (pmclog_read(parser, &ev) == 0) {
+ if (ev.pl_type != PMCLOG_TYPE_CALLCHAIN ||
+ ev.pl_u.pl_cc.pl_pmcid != id)
+ continue;
+ nrec++;
+ if ((ev.pl_u.pl_cc.pl_cpuflags & PMC_CC_F_MULTIPART) == 0) {
+ bad++;
+ continue;
+ }
+ /* Check data and a PC. */
+ len = PMC_MULTIPART_HEADER_LENGTH / sizeof(uintptr_t);
+ hdr = (uint8_t *)&ev.pl_u.pl_cc.pl_pc[0];
+ for (i = 0; i < PMC_MULTIPART_HEADER_ENTRIES; i++) {
+ if (hdr[2 * i] == PMC_CC_MULTIPART_NONE)
+ break;
+ len += hdr[2 * i + 1];
+ }
+ if (ev.pl_u.pl_cc.pl_npc <= len)
+ bad++;
+ }
+ ATF_CHECK_MSG(ev.pl_state == PMCLOG_EOF, "log state %d",
+ ev.pl_state);
+ pmclog_close(parser);
+ close(fd);
+
+ printf("throttled %ju, records %ju, bad %ju\n", (uintmax_t)throttled,
+ (uintmax_t)nrec, (uintmax_t)bad);
+ ATF_CHECK_MSG(throttled > 0, "the PMC never reached the limit");
+ ATF_CHECK_MSG(nrec > 0, "no sample in the log");
+ ATF_CHECK_EQ_MSG(bad, 0, "%ju of %ju samples lost the IBS data",
+ (uintmax_t)bad, (uintmax_t)nrec);
+}
+
+ATF_TC_CLEANUP(pconly_ibs, tc)
+{
+
+ sysctls_restore();
+}
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, rate_limited);
@@ -646,5 +718,6 @@
ATF_TP_ADD_TC(tp, drop_records_process);
ATF_TP_ADD_TC(tp, short_period);
ATF_TP_ADD_TC(tp, flush_loop);
+ ATF_TP_ADD_TC(tp, pconly_ibs);
return (atf_no_error());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 11, 2:00 AM (11 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41652416
Default Alt Text
D61374.1794362440.diff (5 KB)
Attached To
Mode
D61374: hwpmc: use PC-only samples after throttles
Attached
Detach File
Event Timeline