diff options
Diffstat (limited to 'static/freebsd/man4/hwpmc.4 3.html')
| -rw-r--r-- | static/freebsd/man4/hwpmc.4 3.html | 755 |
1 files changed, 755 insertions, 0 deletions
diff --git a/static/freebsd/man4/hwpmc.4 3.html b/static/freebsd/man4/hwpmc.4 3.html new file mode 100644 index 00000000..a1ad831b --- /dev/null +++ b/static/freebsd/man4/hwpmc.4 3.html @@ -0,0 +1,755 @@ +<table class="head"> + <tr> + <td class="head-ltitle">HWPMC(4)</td> + <td class="head-vol">Device Drivers Manual</td> + <td class="head-rtitle">HWPMC(4)</td> + </tr> +</table> +<div class="manual-text"> +<section class="Sh"> +<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1> +<p class="Pp"><code class="Nm">hwpmc</code> — <span class="Nd">Hardware + Performance Monitoring Counter support</span></p> +</section> +<section class="Sh"> +<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1> +<p class="Pp">The following option must be present in the kernel configuration + file:</p> +<div class="Bd Pp Bd-indent"><code class="Cd">options HWPMC_HOOKS</code></div> +<p class="Pp">Additionally, for i386 systems:</p> +<div class="Bd Pp Bd-indent"><code class="Cd">device apic</code></div> +<p class="Pp">To load the driver as a module at boot time:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>sysrc kld_list+=hwpmc</pre> +</div> +<p class="Pp">Alternatively, to compile the driver into the kernel:</p> +<div class="Bd Pp Bd-indent"><code class="Cd">device hwpmc</code></div> +<p class="Pp">To enable debugging features (see + <a class="Sx" href="#DEBUGGING">DEBUGGING</a>):</p> +<div class="Bd Pp Bd-indent"><code class="Cd">options KTR</code> +<br/> +<code class="Cd">options KTR_COMPILE=(KTR_SUBSYS)</code> +<br/> +<code class="Cd">options KTR_MASK=(KTR_SUBSYS)</code> +<br/> +<code class="Cd">options HWPMC_DEBUG</code></div> +</section> +<section class="Sh"> +<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1> +<p class="Pp">The <code class="Nm">hwpmc</code> driver virtualizes the hardware + performance monitoring facilities in modern CPUs and provides support for + using these facilities from user level processes.</p> +<p class="Pp">The driver supports multi-processor systems.</p> +<p class="Pp">PMCs are allocated using the + <code class="Dv">PMC_OP_PMCALLOCATE</code> request. A successful + <code class="Dv">PMC_OP_PMCALLOCATE</code> request will return a handle to + the requesting process. Subsequent operations on the allocated PMC use this + handle to denote the specific PMC. A process that has successfully allocated + a PMC is termed an “owner process”.</p> +<p class="Pp">PMCs may be allocated with process or system scope.</p> +<dl class="Bl-tag"> + <dt id="Process-scope"><a class="permalink" href="#Process-scope"><i class="Em">Process-scope</i></a></dt> + <dd>The PMC is active only when a thread belonging to a process it is attached + to is scheduled on a CPU.</dd> + <dt id="System-scope"><a class="permalink" href="#System-scope"><i class="Em">System-scope</i></a></dt> + <dd>The PMC operates independently of processes and measures hardware events + for the system as a whole.</dd> +</dl> +<p class="Pp">PMCs may be allocated for counting or for sampling:</p> +<dl class="Bl-tag"> + <dt id="Counting"><a class="permalink" href="#Counting"><i class="Em">Counting</i></a></dt> + <dd>In counting modes, the PMCs count hardware events. These counts are + retrievable using the <code class="Dv">PMC_OP_PMCREAD</code> system call + on all architectures. Some architectures offer faster methods of reading + these counts.</dd> + <dt id="Sampling"><a class="permalink" href="#Sampling"><i class="Em">Sampling</i></a></dt> + <dd>In sampling modes, the PMCs are configured to sample the CPU instruction + pointer (and optionally to capture the call chain leading up to the + sampled instruction pointer) after a configurable number of hardware + events have been observed. Instruction pointer samples and call chain + records are usually directed to a log file for subsequent analysis.</dd> +</dl> +<p class="Pp">Scope and operational mode are orthogonal; a PMC may thus be + configured to operate in one of the following four modes:</p> +<dl class="Bl-tag"> + <dt>Process-scope, counting</dt> + <dd>These PMCs count hardware events whenever a thread in their attached + process is scheduled on a CPU. These PMCs normally count from zero, but + the initial count may be set using the + <code class="Dv">PMC_OP_SETCOUNT</code> operation. Applications can read + the value of the PMC anytime using the + <code class="Dv">PMC_OP_PMCRW</code> operation.</dd> + <dt>Process-scope, sampling</dt> + <dd>These PMCs sample the target processes instruction pointer after they have + seen the configured number of hardware events. The PMCs only count events + when a thread belonging to their attached process is active. The desired + frequency of sampling is set using the + <code class="Dv">PMC_OP_SETCOUNT</code> operation prior to starting the + PMC. Log files are configured using the + <code class="Dv">PMC_OP_CONFIGURELOG</code> operation.</dd> + <dt>System-scope, counting</dt> + <dd>These PMCs count hardware events seen by them independent of the processes + that are executing. The current count on these PMCs can be read using the + <code class="Dv">PMC_OP_PMCRW</code> request. These PMCs normally count + from zero, but the initial count may be set using the + <code class="Dv">PMC_OP_SETCOUNT</code> operation.</dd> + <dt>System-scope, sampling</dt> + <dd>These PMCs will periodically sample the instruction pointer of the CPU + they are allocated on, and will write the sample to a log for further + processing. The desired frequency of sampling is set using the + <code class="Dv">PMC_OP_SETCOUNT</code> operation prior to starting the + PMC. Log files are configured using the + <code class="Dv">PMC_OP_CONFIGURELOG</code> operation. + <p class="Pp">System-wide statistical sampling can only be enabled by a + process with super-user privileges.</p> + </dd> +</dl> +<p class="Pp">Processes are allowed to allocate as many PMCs as the hardware and + current operating conditions permit. Processes may mix allocations of + system-wide and process-private PMCs. Multiple processes may be using PMCs + simultaneously.</p> +<p class="Pp">Allocated PMCs are started using the + <code class="Dv">PMC_OP_PMCSTART</code> operation, and stopped using the + <code class="Dv">PMC_OP_PMCSTOP</code> operation. Stopping and starting a + PMC is permitted at any time the owner process has a valid handle to the + PMC.</p> +<p class="Pp">Process-private PMCs need to be attached to a target process + before they can be used. Attaching a process to a PMC is done using the + <code class="Dv">PMC_OP_PMCATTACH</code> operation. An already attached PMC + may be detached from its target process using the converse + <code class="Dv">PMC_OP_PMCDETACH</code> operation. Issuing a + <code class="Dv">PMC_OP_PMCSTART</code> operation on an as yet unattached + PMC will cause it to be attached to its owner process. The following rules + determine whether a given process may attach a PMC to another target + process:</p> +<ul class="Bl-bullet Bl-compact"> + <li>A non-jailed process with super-user privileges is allowed to attach to + any other process in the system.</li> + <li>Other processes are only allowed to attach to targets that they would be + able to attach to for debugging (as determined by + <a class="Xr">p_candebug(9)</a>).</li> +</ul> +<p class="Pp">PMCs are released using <code class="Dv">PMC_OP_PMCRELEASE</code>. + After a successful <code class="Dv">PMC_OP_PMCRELEASE</code> operation the + handle to the PMC will become invalid.</p> +<section class="Ss"> +<h2 class="Ss" id="Modifier_Flags"><a class="permalink" href="#Modifier_Flags">Modifier + Flags</a></h2> +<p class="Pp">The <code class="Dv">PMC_OP_PMCALLOCATE</code> operation supports + the following flags that modify the behavior of an allocated PMC:</p> +<dl class="Bl-tag"> + <dt id="PMC_F_CALLCHAIN"><a class="permalink" href="#PMC_F_CALLCHAIN"><code class="Dv">PMC_F_CALLCHAIN</code></a></dt> + <dd>This modifier informs sampling PMCs to record a callchain when capturing a + sample. The maximum depth to which call chains are recorded is specified + by the <var class="Va">kern.hwpmc.callchaindepth</var> kernel + tunable.</dd> + <dt id="PMC_F_DESCENDANTS"><a class="permalink" href="#PMC_F_DESCENDANTS"><code class="Dv">PMC_F_DESCENDANTS</code></a></dt> + <dd>This modifier is valid only for a PMC being allocated in process-private + mode. It signifies that the PMC will track hardware events for its target + process and the target's current and future descendants.</dd> + <dt id="PMC_F_LOG_PROCCSW"><a class="permalink" href="#PMC_F_LOG_PROCCSW"><code class="Dv">PMC_F_LOG_PROCCSW</code></a></dt> + <dd>This modifier is valid only for a PMC being allocated in process-private + mode. When this modifier is present, at every context switch, + <code class="Nm">hwpmc</code> will log a record containing the number of + hardware events seen by the target process when it was scheduled on the + CPU.</dd> + <dt id="PMC_F_LOG_PROCEXIT"><a class="permalink" href="#PMC_F_LOG_PROCEXIT"><code class="Dv">PMC_F_LOG_PROCEXIT</code></a></dt> + <dd>This modifier is valid only for a PMC being allocated in process-private + mode. With this modifier present, <code class="Nm">hwpmc</code> will + maintain per-process counts for each target process attached to a PMC. At + process exit time, a record containing the target process' PID and the + accumulated per-process count for that process will be written to the + configured log file.</dd> +</dl> +<p class="Pp">Modifiers <code class="Dv">PMC_F_LOG_PROCEXIT</code> and + <code class="Dv">PMC_F_LOG_PROCCSW</code> may be used in combination with + modifier <code class="Dv">PMC_F_DESCENDANTS</code> to track the behavior of + complex pipelines of processes. PMCs with modifiers + <code class="Dv">PMC_F_LOG_PROCEXIT</code> and + <code class="Dv">PMC_F_LOG_PROCCSW</code> cannot be started until their + owner process has configured a log file.</p> +</section> +<section class="Ss"> +<h2 class="Ss" id="Signals"><a class="permalink" href="#Signals">Signals</a></h2> +<p class="Pp">The <code class="Nm">hwpmc</code> driver may deliver signals to + processes that have allocated PMCs:</p> +<dl class="Bl-tag"> + <dt id="SIGIO"><a class="permalink" href="#SIGIO"><code class="Dv">SIGIO</code></a></dt> + <dd>A <code class="Dv">PMC_OP_PMCRW</code> operation was attempted on a + process-private PMC that does not have attached target processes.</dd> + <dt id="SIGBUS"><a class="permalink" href="#SIGBUS"><code class="Dv">SIGBUS</code></a></dt> + <dd>The <code class="Nm">hwpmc</code> driver is being unloaded from the + kernel.</dd> +</dl> +</section> +<section class="Ss"> +<h2 class="Ss" id="PMC_ROW_DISPOSITIONS"><a class="permalink" href="#PMC_ROW_DISPOSITIONS">PMC + ROW DISPOSITIONS</a></h2> +<p class="Pp">A PMC row is defined as the set of PMC resources at the same + hardware address in the CPUs in a system. Since process scope PMCs need to + move between CPUs following their target threads, allocation of a process + scope PMC reserves all PMCs in a PMC row for use only with process scope + PMCs. Accordingly a PMC row will be in one of the following + dispositions:</p> +<dl class="Bl-tag Bl-compact"> + <dt id="PMC_DISP_FREE"><a class="permalink" href="#PMC_DISP_FREE"><code class="Dv">PMC_DISP_FREE</code></a></dt> + <dd>Hardware counters in this row are free and may be use to satisfy either of + system scope or process scope allocation requests.</dd> + <dt id="PMC_DISP_THREAD"><a class="permalink" href="#PMC_DISP_THREAD"><code class="Dv">PMC_DISP_THREAD</code></a></dt> + <dd>Hardware counters in this row are in use by process scope PMCs and are + only available for process scope allocation requests.</dd> + <dt id="PMC_DISP_STANDALONE"><a class="permalink" href="#PMC_DISP_STANDALONE"><code class="Dv">PMC_DISP_STANDALONE</code></a></dt> + <dd>Some hardware counters in this row have been administratively disabled or + are in use by system scope PMCs. Non-disabled hardware counters in such a + row may be used for satisfying system scope allocation requests. No + process scope PMCs will use hardware counters in this row.</dd> +</dl> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="COMPATIBILITY"><a class="permalink" href="#COMPATIBILITY">COMPATIBILITY</a></h1> +<p class="Pp">The API and ABI documented in this manual page may change in the + future. This interface is intended to be consumed by the + <a class="Xr">pmc(3)</a> library; other consumers are unsupported. + Applications targeting PMCs should use the <a class="Xr">pmc(3)</a> library + API.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="PROGRAMMING_API"><a class="permalink" href="#PROGRAMMING_API">PROGRAMMING + API</a></h1> +<p class="Pp">The <code class="Nm">hwpmc</code> driver operates using a system + call number that is dynamically allotted to it when it is loaded into the + kernel.</p> +<p class="Pp">The <code class="Nm">hwpmc</code> driver supports the following + operations:</p> +<dl class="Bl-tag"> + <dt id="PMC_OP_CONFIGURELOG"><a class="permalink" href="#PMC_OP_CONFIGURELOG"><code class="Dv">PMC_OP_CONFIGURELOG</code></a></dt> + <dd>Configure a log file for PMCs that require a log file. The + <code class="Nm">hwpmc</code> driver will write log data to this file + asynchronously. If it encounters an error, logging will be stopped and the + error code encountered will be saved for subsequent retrieval by a + <code class="Dv">PMC_OP_FLUSHLOG</code> request.</dd> + <dt id="PMC_OP_FLUSHLOG"><a class="permalink" href="#PMC_OP_FLUSHLOG"><code class="Dv">PMC_OP_FLUSHLOG</code></a></dt> + <dd>Transfer buffered log data inside <code class="Nm">hwpmc</code> to a + configured output file. This operation returns to the caller after the + write operation has returned. The returned error code reflects any pending + error state inside <code class="Nm">hwpmc</code>.</dd> + <dt id="PMC_OP_GETCAPS"><a class="permalink" href="#PMC_OP_GETCAPS"><code class="Dv">PMC_OP_GETCAPS</code></a></dt> + <dd>Retrieve the capabilities associated with a specific PMC counter. Some + capabilities may be limited to specific indices (i.e., not available + across all counters within a class).</dd> + <dt id="PMC_OP_GETCPUINFO"><a class="permalink" href="#PMC_OP_GETCPUINFO"><code class="Dv">PMC_OP_GETCPUINFO</code></a></dt> + <dd>Retrieve information about the highest possible CPU number for the system, + and the number of hardware performance monitoring counters available per + CPU.</dd> + <dt id="PMC_OP_GETDRIVERSTATS"><a class="permalink" href="#PMC_OP_GETDRIVERSTATS"><code class="Dv">PMC_OP_GETDRIVERSTATS</code></a></dt> + <dd>Retrieve module statistics (for analyzing the behavior of + <code class="Nm">hwpmc</code> itself).</dd> + <dt id="PMC_OP_GETMODULEVERSION"><a class="permalink" href="#PMC_OP_GETMODULEVERSION"><code class="Dv">PMC_OP_GETMODULEVERSION</code></a></dt> + <dd>Retrieve the version number of API.</dd> + <dt id="PMC_OP_GETPMCINFO"><a class="permalink" href="#PMC_OP_GETPMCINFO"><code class="Dv">PMC_OP_GETPMCINFO</code></a></dt> + <dd>Retrieve information about the current state of the PMCs on a given + CPU.</dd> + <dt id="PMC_OP_PMCADMIN"><a class="permalink" href="#PMC_OP_PMCADMIN"><code class="Dv">PMC_OP_PMCADMIN</code></a></dt> + <dd>Set the administrative state (i.e., whether enabled or disabled) for the + hardware PMCs managed by the <code class="Nm">hwpmc</code> driver. The + invoking process needs to possess the + <code class="Dv">PRIV_PMC_MANAGE</code> privilege.</dd> + <dt id="PMC_OP_PMCALLOCATE"><a class="permalink" href="#PMC_OP_PMCALLOCATE"><code class="Dv">PMC_OP_PMCALLOCATE</code></a></dt> + <dd>Allocate and configure a PMC. On successful allocation, a handle to the + PMC (a 32 bit value) is returned.</dd> + <dt id="PMC_OP_PMCATTACH"><a class="permalink" href="#PMC_OP_PMCATTACH"><code class="Dv">PMC_OP_PMCATTACH</code></a></dt> + <dd>Attach a process mode PMC to a target process. The PMC will be active + whenever a thread in the target process is scheduled on a CPU. + <p class="Pp">If the <code class="Dv">PMC_F_DESCENDANTS</code> flag had been + specified at PMC allocation time, then the PMC is attached to all + current and future descendants of the target process.</p> + </dd> + <dt id="PMC_OP_PMCDETACH"><a class="permalink" href="#PMC_OP_PMCDETACH"><code class="Dv">PMC_OP_PMCDETACH</code></a></dt> + <dd>Detach a PMC from its target process.</dd> + <dt id="PMC_OP_PMCRELEASE"><a class="permalink" href="#PMC_OP_PMCRELEASE"><code class="Dv">PMC_OP_PMCRELEASE</code></a></dt> + <dd>Release a PMC.</dd> + <dt id="PMC_OP_PMCRW"><a class="permalink" href="#PMC_OP_PMCRW"><code class="Dv">PMC_OP_PMCRW</code></a></dt> + <dd>Read and write a PMC. This operation is valid only for PMCs configured in + counting modes.</dd> + <dt id="PMC_OP_SETCOUNT"><a class="permalink" href="#PMC_OP_SETCOUNT"><code class="Dv">PMC_OP_SETCOUNT</code></a></dt> + <dd>Set the initial count (for counting mode PMCs) or the desired sampling + rate (for sampling mode PMCs).</dd> + <dt id="PMC_OP_PMCSTART"><a class="permalink" href="#PMC_OP_PMCSTART"><code class="Dv">PMC_OP_PMCSTART</code></a></dt> + <dd>Start a PMC.</dd> + <dt id="PMC_OP_PMCSTOP"><a class="permalink" href="#PMC_OP_PMCSTOP"><code class="Dv">PMC_OP_PMCSTOP</code></a></dt> + <dd>Stop a PMC.</dd> + <dt id="PMC_OP_WRITELOG"><a class="permalink" href="#PMC_OP_WRITELOG"><code class="Dv">PMC_OP_WRITELOG</code></a></dt> + <dd>Insert a timestamped user record into the log file.</dd> +</dl> +<section class="Ss"> +<h2 class="Ss" id="i386_Specific_API"><a class="permalink" href="#i386_Specific_API">i386 + Specific API</a></h2> +<p class="Pp">Some i386 family CPUs support the RDPMC instruction which allows a + user process to read a PMC value without needing to invoke a + <code class="Dv">PMC_OP_PMCRW</code> operation. On such CPUs, the machine + address associated with an allocated PMC is retrievable using the + <code class="Dv">PMC_OP_PMCX86GETMSR</code> system call.</p> +<dl class="Bl-tag"> + <dt id="PMC_OP_PMCX86GETMSR"><a class="permalink" href="#PMC_OP_PMCX86GETMSR"><code class="Dv">PMC_OP_PMCX86GETMSR</code></a></dt> + <dd>Retrieve the MSR (machine specific register) number associated with the + given PMC handle. + <p class="Pp">The PMC needs to be in process-private mode and allocated + without the <code class="Dv">PMC_F_DESCENDANTS</code> modifier flag, and + should be attached only to its owner process at the time of the + call.</p> + </dd> +</dl> +</section> +<section class="Ss"> +<h2 class="Ss" id="amd64_Specific_API"><a class="permalink" href="#amd64_Specific_API">amd64 + Specific API</a></h2> +<p class="Pp">AMD64 CPUs support the RDPMC instruction which allows a user + process to read a PMC value without needing to invoke a + <code class="Dv">PMC_OP_PMCRW</code> operation. The machine address + associated with an allocated PMC is retrievable using the + <code class="Dv">PMC_OP_PMCX86GETMSR</code> system call.</p> +<dl class="Bl-tag"> + <dt id="PMC_OP_PMCX86GETMSR~2"><a class="permalink" href="#PMC_OP_PMCX86GETMSR~2"><code class="Dv">PMC_OP_PMCX86GETMSR</code></a></dt> + <dd>Retrieve the MSR (machine specific register) number associated with the + given PMC handle. + <p class="Pp">The PMC needs to be in process-private mode and allocated + without the <code class="Dv">PMC_F_DESCENDANTS</code> modifier flag, and + should be attached only to its owner process at the time of the + call.</p> + </dd> +</dl> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="SYSCTL_VARIABLES_AND_LOADER_TUNABLES"><a class="permalink" href="#SYSCTL_VARIABLES_AND_LOADER_TUNABLES">SYSCTL + VARIABLES AND LOADER TUNABLES</a></h1> +<p class="Pp">The behavior of <code class="Nm">hwpmc</code> is influenced by the + following <a class="Xr">sysctl(8)</a> and <a class="Xr">loader(8)</a> + tunables:</p> +<dl class="Bl-tag"> + <dt id="kern.hwpmc.callchaindepth"><var class="Va">kern.hwpmc.callchaindepth</var> + (integer, read-only)</dt> + <dd>The maximum number of call chain records to capture per sample. The + default is 8.</dd> + <dt id="kern.hwpmc.debugflags"><var class="Va">kern.hwpmc.debugflags</var> + (string, read-write)</dt> + <dd>(Only available if the <code class="Nm">hwpmc</code> driver was compiled + with <code class="Fl">-DDEBUG</code>.) Control the verbosity of debug + messages from the <code class="Nm">hwpmc</code> driver.</dd> + <dt id="kern.hwpmc.hashsize"><var class="Va">kern.hwpmc.hashsize</var> + (integer, read-only)</dt> + <dd>The number of rows in the hash tables used to keep track of owner and + target processes. The default is 16.</dd> + <dt id="kern.hwpmc.logbuffersize"><var class="Va">kern.hwpmc.logbuffersize</var> + (integer, read-only)</dt> + <dd>The size in kilobytes of each log buffer used by + <code class="Nm">hwpmc</code>'s logging function. The default buffer size + is 256KB. The maximum value is 16MB.</dd> + <dt id="kern.hwpmc.mincount"><var class="Va">kern.hwpmc.mincount</var> + (integer, read-write)</dt> + <dd>The minimum sampling rate for sampling mode PMCs. The default count is + 1000 events.</dd> + <dt id="kern.hwpmc.mtxpoolsize"><var class="Va">kern.hwpmc.mtxpoolsize</var> + (integer, read-only)</dt> + <dd>The size of the spin mutex pool used by the PMC driver. The default is + 32.</dd> + <dt id="kern.hwpmc.nbuffers_pcpu"><var class="Va">kern.hwpmc.nbuffers_pcpu</var> + (integer, read-only)</dt> + <dd>The number of log buffers per CPU used by <code class="Nm">hwpmc</code> + for logging. The default is 32. The product of + <var class="Va">kern.hwpmc.nbuffers_pcpu</var> and + <var class="Va">kern.hwpmc.logbuffersize</var> must not exceed 32MB per + CPU.</dd> + <dt id="kern.hwpmc.nsamples"><var class="Va">kern.hwpmc.nsamples</var> + (integer, read-only)</dt> + <dd>The number of entries in the per-CPU ring buffer used during sampling. The + default is 512.</dd> + <dt id="security.bsd.unprivileged_syspmcs"><var class="Va">security.bsd.unprivileged_syspmcs</var> + (boolean, read-write)</dt> + <dd>If set to non-zero, allow unprivileged processes to allocate system-wide + PMCs. The default value is 0.</dd> + <dt id="security.bsd.unprivileged_proc_debug"><var class="Va">security.bsd.unprivileged_proc_debug</var> + (boolean, read-write)</dt> + <dd>If set to 0, the <code class="Nm">hwpmc</code> driver will only allow + privileged processes to attach PMCs to other processes.</dd> +</dl> +<p class="Pp">These variables may be set in the kernel environment using + <a class="Xr">kenv(1)</a> before <code class="Nm">hwpmc</code> is + loaded.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="IMPLEMENTATION_NOTES"><a class="permalink" href="#IMPLEMENTATION_NOTES">IMPLEMENTATION + NOTES</a></h1> +<section class="Ss"> +<h2 class="Ss" id="SMP_Symmetry"><a class="permalink" href="#SMP_Symmetry">SMP + Symmetry</a></h2> +<p class="Pp">The kernel driver requires all physical CPUs in an SMP system to + have identical performance monitoring counter hardware.</p> +</section> +<section class="Ss"> +<h2 class="Ss" id="Sparse_CPU_Numbering"><a class="permalink" href="#Sparse_CPU_Numbering">Sparse + CPU Numbering</a></h2> +<p class="Pp">On platforms that sparsely number CPUs and which support + hot-plugging of CPUs, requests that specify non-existent or disabled CPUs + will fail with an error. Applications allocating system-scope PMCs need to + be aware of the possibility of such transient failures.</p> +</section> +<section class="Ss"> +<h2 class="Ss" id="x86_TSC_Handling"><a class="permalink" href="#x86_TSC_Handling">x86 + TSC Handling</a></h2> +<p class="Pp">Historically, on the x86 architecture, + <span class="Ux">FreeBSD</span> has permitted user processes running at a + processor CPL of 3 to read the TSC using the RDTSC instruction. The + <code class="Nm">hwpmc</code> driver preserves this behavior.</p> +</section> +<section class="Ss"> +<h2 class="Ss" id="Intel_P4/HTT_Handling"><a class="permalink" href="#Intel_P4/HTT_Handling">Intel + P4/HTT Handling</a></h2> +<p class="Pp">On CPUs with HTT support, Intel P4 PMCs are capable of qualifying + only a subset of hardware events on a per-logical CPU basis. Consequently, + if HTT is enabled on a system with Intel Pentium P4 PMCs, then the + <code class="Nm">hwpmc</code> driver will reject allocation requests for + process-private PMCs that request counting of hardware events that cannot be + counted separately for each logical CPU.</p> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="DIAGNOSTICS"><a class="permalink" href="#DIAGNOSTICS">DIAGNOSTICS</a></h1> +<dl class="Bl-diag"> + <dt>hwpmc: [class/npmc/capabilities]...</dt> + <dd>Announce the presence of <var class="Va">npmc</var> PMCs of class + <var class="Va">class</var>, with capabilities described by bit string + <var class="Va">capabilities</var>.</dd> + <dt>hwpmc: kernel version (0x%x) does not match module version (0x%x).</dt> + <dd>The module loading process failed because a version mismatch was detected + between the currently executing kernel and the module being loaded.</dd> + <dt>hwpmc: this kernel has not been compiled with 'options HWPMC_HOOKS'.</dt> + <dd>The module loading process failed because the currently executing kernel + was not configured with the required configuration option + <code class="Dv">HWPMC_HOOKS</code>.</dd> + <dt>hwpmc: tunable hashsize=%d must be greater than zero.</dt> + <dd>A negative value was supplied for tunable + <var class="Va">kern.hwpmc.hashsize</var>.</dd> + <dt>hwpmc: logbuffersize=%d must be greater than zero and less than or equal + to %d, resetting to %d.</dt> + <dd>A negative value was supplied for tunable + <var class="Va">kern.hwpmc.logbuffersize</var>.</dd> + <dt>hwpmc: nbuffers_pcpu=%d must be greater than zero, resetting to %d.</dt> + <dd>A negative value was supplied for tunable + <var class="Va">kern.hwpmc.nbuffers_pcpu</var>.</dd> + <dt>hwpmc: tunable nsamples=%d out of range.</dt> + <dd>The value for tunable <var class="Va">kern.hwpmc.nsamples</var> was + negative or greater than 65535.</dd> + <dt>hwpmc: nbuffers_pcpu=%d * logbuffersize=%d exceeds %dMB per CPU limit, + resetting to defaults (%d * %d).</dt> + <dd>The product of tunables <var class="Va">kern.hwpmc.nbuffers_pcpu</var> and + <var class="Va">kern.hwpmc.logbuffersize</var> exceeds the maximum per-CPU + memory limit. Both tunables are reset to their compiled defaults.</dd> +</dl> +</section> +<section class="Sh"> +<h1 class="Sh" id="DEBUGGING"><a class="permalink" href="#DEBUGGING">DEBUGGING</a></h1> +<p class="Pp">The <code class="Nm">hwpmc</code> module can be configured to + record trace entries using the <a class="Xr">ktr(4)</a> interface. This is + useful for debugging the driver's functionality, primarily during + development. This debugging functionality is not enabled by default, and + requires recompiling the kernel and <code class="Nm">hwpmc</code> module + after adding the following to the kernel config:</p> +<div class="Bd Pp Bd-indent Li"> +<pre><code class="Cd">options KTR</code> +<code class="Cd">options KTR_COMPILE=(KTR_SUBSYS)</code> +<code class="Cd">options KTR_MASK=(KTR_SUBSYS)</code> +<code class="Cd">options HWPMC_DEBUG</code></pre> +</div> +<p class="Pp">This alone is not enough to enable tracing; one must also + configure the <var class="Va">kern.hwpmc.debugflags</var> + <a class="Xr">sysctl(8)</a> variable, which provides fine-grained control + over which types of events are logged to the trace buffer.</p> +<p class="Pp"><code class="Nm">hwpmc</code> trace events are grouped by 'major' + and 'minor' flag types. The major flag names are as follows:</p> +<p class="Pp"></p> +<div class="Bd-indent"> +<dl class="Bl-tag Bl-compact"> + <dt>cpu</dt> + <dd>CPU events</dd> + <dt>csw</dt> + <dd>Context switch events</dd> + <dt>logging</dt> + <dd>Logging events</dd> + <dt>md</dt> + <dd>Machine-dependent/class-dependent events</dd> + <dt>module</dt> + <dd>Miscellaneous events</dd> + <dt>owner</dt> + <dd>PMC owner events</dd> + <dt>pmc</dt> + <dd>PMC management events</dd> + <dt>process</dt> + <dd>Process events</dd> + <dt>sampling</dt> + <dd>Sampling events</dd> +</dl> +</div> +<p class="Pp">The minor flags for each major flag group can vary. The individual + minor flag names are:</p> +<div class="Bd Pp Bd-indent">allocaterow, allocate, attach, bind, config, exec, + exit, find, flush, fork, getbuf, hook, init, intr, linktarget, mayberemove, + ops, read, register, release, remove, sample, scheduleio, select, signal, swi, + swo, start, stop, syscall, unlinktarget, write</div> +<p class="Pp">The <var class="Va">kern.hwpmc.debugflags</var> variable is a + string with a custom format. The string should contain a space-separated + list of event specifiers. Each event specifier consists of the major flag + name, followed by an equal sign (=), followed by a comma-separated list of + minor event types. To track all events for a major group, an asterisk (*) + can be given instead of minor event names.</p> +<p class="Pp">For example, to trace all allocation and release events, set + <var class="Va">debugflags</var> as follows:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>kern.hwpmc.debugflags="pmc=allocate,release md=allocate,release"</pre> +</div> +<p class="Pp">To trace all events in the process and context switch major flag + groups:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>kern.hwpmc.debugflags="process=* csw=*"</pre> +</div> +<p class="Pp">To disable all trace events, set the variable to an empty + string.</p> +<div class="Bd Pp Bd-indent Li"> +<pre>kern.hwpmc.debugflags=""</pre> +</div> +<p class="Pp">Trace events are recorded by <a class="Xr">ktr(4)</a>, and can be + inspected at run-time using the <a class="Xr">ktrdump(8)</a> utility, or at + the <a class="Xr">ddb(4)</a> prompt after a panic with the 'show ktr' + command.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="ERRORS"><a class="permalink" href="#ERRORS">ERRORS</a></h1> +<p class="Pp">A command issued to the <code class="Nm">hwpmc</code> driver may + fail with the following errors:</p> +<dl class="Bl-tag"> + <dt id="EAGAIN">[<a class="permalink" href="#EAGAIN"><code class="Er">EAGAIN</code></a>]</dt> + <dd>Helper process creation failed for a + <code class="Dv">PMC_OP_CONFIGURELOG</code> request due to a temporary + resource shortage in the kernel.</dd> + <dt id="EBUSY">[<a class="permalink" href="#EBUSY"><code class="Er">EBUSY</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_CONFIGURELOG</code> operation was requested + while an existing log was active.</dd> + <dt id="EBUSY~2">[<a class="permalink" href="#EBUSY~2"><code class="Er">EBUSY</code></a>]</dt> + <dd>A DISABLE operation was requested using the + <code class="Dv">PMC_OP_PMCADMIN</code> request for a set of hardware + resources currently in use for process-private PMCs.</dd> + <dt id="EBUSY~3">[<a class="permalink" href="#EBUSY~3"><code class="Er">EBUSY</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCADMIN</code> operation was requested on an + active system mode PMC.</dd> + <dt id="EBUSY~4">[<a class="permalink" href="#EBUSY~4"><code class="Er">EBUSY</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCATTACH</code> operation was requested for a + target process that already had another PMC using the same hardware + resources attached to it.</dd> + <dt id="EBUSY~5">[<a class="permalink" href="#EBUSY~5"><code class="Er">EBUSY</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCRW</code> request writing a new value was + issued on a PMC that was active.</dd> + <dt id="EBUSY~6">[<a class="permalink" href="#EBUSY~6"><code class="Er">EBUSY</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCSETCOUNT</code> request was issued on a PMC + that was active.</dd> + <dt id="EDOOFUS">[<a class="permalink" href="#EDOOFUS"><code class="Er">EDOOFUS</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCSTART</code> operation was requested without + a log file being configured for a PMC allocated with + <code class="Dv">PMC_F_LOG_PROCCSW</code> and + <code class="Dv">PMC_F_LOG_PROCEXIT</code> modifiers.</dd> + <dt id="EDOOFUS~2">[<a class="permalink" href="#EDOOFUS~2"><code class="Er">EDOOFUS</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCSTART</code> operation was requested on a + system-wide sampling PMC without a log file being configured.</dd> + <dt id="EEXIST">[<a class="permalink" href="#EEXIST"><code class="Er">EEXIST</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCATTACH</code> request was reissued for a + target process that already is the target of this PMC.</dd> + <dt id="EFAULT">[<a class="permalink" href="#EFAULT"><code class="Er">EFAULT</code></a>]</dt> + <dd>A bad address was passed in to the driver.</dd> + <dt id="EINVAL">[<a class="permalink" href="#EINVAL"><code class="Er">EINVAL</code></a>]</dt> + <dd>An invalid PMC handle was specified.</dd> + <dt id="EINVAL~2">[<a class="permalink" href="#EINVAL~2"><code class="Er">EINVAL</code></a>]</dt> + <dd>An invalid CPU number was passed in for a + <code class="Dv">PMC_OP_GETPMCINFO</code> operation.</dd> + <dt id="EINVAL~3">[<a class="permalink" href="#EINVAL~3"><code class="Er">EINVAL</code></a>]</dt> + <dd>The <var class="Ar">pm_flags</var> argument to a + <code class="Dv">PMC_OP_CONFIGURELOG</code> request contained unknown + flags.</dd> + <dt id="EINVAL~4">[<a class="permalink" href="#EINVAL~4"><code class="Er">EINVAL</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_CONFIGURELOG</code> request to de-configure a + log file was issued without a log file being configured.</dd> + <dt id="EINVAL~5">[<a class="permalink" href="#EINVAL~5"><code class="Er">EINVAL</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_FLUSHLOG</code> request was issued without a log + file being configured.</dd> + <dt id="EINVAL~6">[<a class="permalink" href="#EINVAL~6"><code class="Er">EINVAL</code></a>]</dt> + <dd>An invalid CPU number was passed in for a + <code class="Dv">PMC_OP_PMCADMIN</code> operation.</dd> + <dt id="EINVAL~7">[<a class="permalink" href="#EINVAL~7"><code class="Er">EINVAL</code></a>]</dt> + <dd>An invalid operation request was passed in for a + <code class="Dv">PMC_OP_PMCADMIN</code> operation.</dd> + <dt id="EINVAL~8">[<a class="permalink" href="#EINVAL~8"><code class="Er">EINVAL</code></a>]</dt> + <dd>An invalid PMC ID was passed in for a + <code class="Dv">PMC_OP_PMCADMIN</code> operation.</dd> + <dt id="EINVAL~9">[<a class="permalink" href="#EINVAL~9"><code class="Er">EINVAL</code></a>]</dt> + <dd>A suitable PMC matching the parameters passed in to a + <code class="Dv">PMC_OP_PMCALLOCATE</code> request could not be + allocated.</dd> + <dt id="EINVAL~10">[<a class="permalink" href="#EINVAL~10"><code class="Er">EINVAL</code></a>]</dt> + <dd>An invalid PMC mode was requested during a + <code class="Dv">PMC_OP_PMCALLOCATE</code> request.</dd> + <dt id="EINVAL~11">[<a class="permalink" href="#EINVAL~11"><code class="Er">EINVAL</code></a>]</dt> + <dd>An invalid CPU number was specified during a + <code class="Dv">PMC_OP_PMCALLOCATE</code> request.</dd> + <dt id="EINVAL~12">[<a class="permalink" href="#EINVAL~12"><code class="Er">EINVAL</code></a>]</dt> + <dd>A CPU other than <code class="Dv">PMC_CPU_ANY</code> was specified in a + <code class="Dv">PMC_OP_PMCALLOCATE</code> request for a process-private + PMC.</dd> + <dt id="EINVAL~13">[<a class="permalink" href="#EINVAL~13"><code class="Er">EINVAL</code></a>]</dt> + <dd>A CPU number of <code class="Dv">PMC_CPU_ANY</code> was specified in a + <code class="Dv">PMC_OP_PMCALLOCATE</code> request for a system-wide + PMC.</dd> + <dt id="EINVAL~14">[<a class="permalink" href="#EINVAL~14"><code class="Er">EINVAL</code></a>]</dt> + <dd>The <var class="Ar">pm_flags</var> argument to an + <code class="Dv">PMC_OP_PMCALLOCATE</code> request contained unknown + flags.</dd> + <dt id="EINVAL~15">[<a class="permalink" href="#EINVAL~15"><code class="Er">EINVAL</code></a>]</dt> + <dd>(On Intel Pentium 4 CPUs with HTT support) A + <code class="Dv">PMC_OP_PMCALLOCATE</code> request for a process-private + PMC was issued for an event that does not support counting on a + per-logical CPU basis.</dd> + <dt id="EINVAL~16">[<a class="permalink" href="#EINVAL~16"><code class="Er">EINVAL</code></a>]</dt> + <dd>A PMC allocated for system-wide operation was specified with a + <code class="Dv">PMC_OP_PMCATTACH</code> or + <code class="Dv">PMC_OP_PMCDETACH</code> request.</dd> + <dt id="EINVAL~17">[<a class="permalink" href="#EINVAL~17"><code class="Er">EINVAL</code></a>]</dt> + <dd>The <var class="Ar">pm_pid</var> argument to a + <code class="Dv">PMC_OP_PMCATTACH</code> or + <code class="Dv">PMC_OP_PMCDETACH</code> request specified an illegal + process ID.</dd> + <dt id="EINVAL~18">[<a class="permalink" href="#EINVAL~18"><code class="Er">EINVAL</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCDETACH</code> request was issued for a PMC + not attached to the target process.</dd> + <dt id="EINVAL~19">[<a class="permalink" href="#EINVAL~19"><code class="Er">EINVAL</code></a>]</dt> + <dd>Argument <var class="Ar">pm_flags</var> to a + <code class="Dv">PMC_OP_PMCRW</code> request contained illegal flags.</dd> + <dt id="EINVAL~20">[<a class="permalink" href="#EINVAL~20"><code class="Er">EINVAL</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCX86GETMSR</code> operation was requested for + a PMC not in process-virtual mode, or for a PMC that is not solely + attached to its owner process, or for a PMC that was allocated with flag + <code class="Dv">PMC_F_DESCENDANTS</code>.</dd> + <dt id="EINVAL~21">[<a class="permalink" href="#EINVAL~21"><code class="Er">EINVAL</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_WRITELOG</code> request was issued for an owner + process without a log file configured.</dd> + <dt id="ENOMEM">[<a class="permalink" href="#ENOMEM"><code class="Er">ENOMEM</code></a>]</dt> + <dd>The system was not able to allocate kernel memory.</dd> + <dt id="ENOSYS">[<a class="permalink" href="#ENOSYS"><code class="Er">ENOSYS</code></a>]</dt> + <dd>(On i386 and amd64 architectures) A + <code class="Dv">PMC_OP_PMCX86GETMSR</code> operation was requested for + hardware that does not support reading PMCs directly with the RDPMC + instruction.</dd> + <dt id="ENXIO">[<a class="permalink" href="#ENXIO"><code class="Er">ENXIO</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_GETPMCINFO</code> operation was requested for an + absent or disabled CPU.</dd> + <dt id="ENXIO~2">[<a class="permalink" href="#ENXIO~2"><code class="Er">ENXIO</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCALLOCATE</code> operation specified + allocation of a system-wide PMC on an absent or disabled CPU.</dd> + <dt id="ENXIO~3">[<a class="permalink" href="#ENXIO~3"><code class="Er">ENXIO</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCSTART</code> or + <code class="Dv">PMC_OP_PMCSTOP</code> request was issued for a + system-wide PMC that was allocated on a CPU that is currently absent or + disabled.</dd> + <dt id="EOPNOTSUPP">[<a class="permalink" href="#EOPNOTSUPP"><code class="Er">EOPNOTSUPP</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCALLOCATE</code> request was issued for PMC + capabilities not supported by the specified PMC class.</dd> + <dt id="EOPNOTSUPP~2">[<a class="permalink" href="#EOPNOTSUPP~2"><code class="Er">EOPNOTSUPP</code></a>]</dt> + <dd>(i386 architectures) A sampling mode PMC was requested on a CPU lacking an + APIC.</dd> + <dt id="EPERM">[<a class="permalink" href="#EPERM"><code class="Er">EPERM</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCADMIN</code> request was issued by a process + without super-user privilege or by a jailed super-user process.</dd> + <dt id="EPERM~2">[<a class="permalink" href="#EPERM~2"><code class="Er">EPERM</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCATTACH</code> operation was issued for a + target process that the current process does not have permission to attach + to.</dd> + <dt id="EPERM~3">[<a class="permalink" href="#EPERM~3"><code class="Er">EPERM</code></a>]</dt> + <dd>(i386 and amd64 architectures) A <code class="Dv">PMC_OP_PMCATTACH</code> + operation was issued on a PMC whose MSR has been retrieved using + <code class="Dv">PMC_OP_PMCX86GETMSR</code>.</dd> + <dt id="ESRCH">[<a class="permalink" href="#ESRCH"><code class="Er">ESRCH</code></a>]</dt> + <dd>A process issued a PMC operation request without having allocated any + PMCs.</dd> + <dt id="ESRCH~2">[<a class="permalink" href="#ESRCH~2"><code class="Er">ESRCH</code></a>]</dt> + <dd>A process issued a PMC operation request after the PMC was detached from + all of its target processes.</dd> + <dt id="ESRCH~3">[<a class="permalink" href="#ESRCH~3"><code class="Er">ESRCH</code></a>]</dt> + <dd>A <code class="Dv">PMC_OP_PMCATTACH</code> or + <code class="Dv">PMC_OP_PMCDETACH</code> request specified a non-existent + process ID.</dd> + <dt id="ESRCH~4">[<a class="permalink" href="#ESRCH~4"><code class="Er">ESRCH</code></a>]</dt> + <dd>The target process for a <code class="Dv">PMC_OP_PMCDETACH</code> + operation is not being monitored by <code class="Nm">hwpmc</code>.</dd> +</dl> +</section> +<section class="Sh"> +<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE + ALSO</a></h1> +<p class="Pp"><a class="Xr">kenv(1)</a>, <a class="Xr">pmc(3)</a>, + <a class="Xr">pmclog(3)</a>, <a class="Xr">ddb(4)</a>, + <a class="Xr">ktr(4)</a>, <a class="Xr">kldload(8)</a>, + <a class="Xr">ktrdump(8)</a>, <a class="Xr">pmccontrol(8)</a>, + <a class="Xr">pmcstat(8)</a>, <a class="Xr">sysctl(8)</a>, + <a class="Xr">kproc_create(9)</a>, <a class="Xr">p_candebug(9)</a></p> +</section> +<section class="Sh"> +<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1> +<p class="Pp">The <code class="Nm">hwpmc</code> driver first appeared in + <span class="Ux">FreeBSD 6.0</span>.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1> +<p class="Pp">The <code class="Nm">hwpmc</code> driver was written by + <span class="An">Joseph Koshy</span> + <<a class="Mt" href="mailto:jkoshy@FreeBSD.org">jkoshy@FreeBSD.org</a>>.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="BUGS"><a class="permalink" href="#BUGS">BUGS</a></h1> +<p class="Pp">The driver samples the state of the kernel's logical processor + support at the time of initialization (i.e., at module load time). On CPUs + supporting logical processors, the driver could misbehave if logical + processors are subsequently enabled or disabled while the driver is + active.</p> +<p class="Pp">On the i386 architecture, the driver requires that the local APIC + on the CPU be enabled for sampling mode to be supported. Many + single-processor motherboards keep the APIC disabled in BIOS; on such + systems <code class="Nm">hwpmc</code> will not support sampling PMCs.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="SECURITY_CONSIDERATIONS"><a class="permalink" href="#SECURITY_CONSIDERATIONS">SECURITY + CONSIDERATIONS</a></h1> +<p class="Pp">PMCs may be used to monitor the actual behavior of the system on + hardware. In situations where this constitutes an undesirable information + leak, the following options are available:</p> +<ol class="Bl-enum"> + <li>Set the <a class="Xr">sysctl(8)</a> tunable + <var class="Va">security.bsd.unprivileged_syspmcs</var> to 0. This ensures + that unprivileged processes cannot allocate system-wide PMCs and thus + cannot observe the hardware behavior of the system as a whole. This + tunable may also be set at boot time using <a class="Xr">loader(8)</a>, or + with <a class="Xr">kenv(1)</a> prior to loading the + <code class="Nm">hwpmc</code> driver into the kernel.</li> + <li>Set the <a class="Xr">sysctl(8)</a> tunable + <var class="Va">security.bsd.unprivileged_proc_debug</var> to 0. This will + ensure that an unprivileged process cannot attach a PMC to any process + other than itself and thus cannot observe the hardware behavior of other + processes with the same credentials.</li> +</ol> +<p class="Pp">System administrators should note that on IA-32 platforms + <span class="Ux">FreeBSD</span> makes the content of the IA-32 TSC counter + available to all processes via the RDTSC instruction.</p> +</section> +</div> +<table class="foot"> + <tr> + <td class="foot-date">July 8, 2023</td> + <td class="foot-os">FreeBSD 15.0</td> + </tr> +</table> |
