libdtrace: Fix an off-by-one in CPU ID handling

The illumos-specific _SC_CPUID_MAX is the largest CPU ID in the system.  This
was mapped to _SC_NPROCESSORS_CONF, which is the total number of CPUs recognized
by the kernel.  If CPU IDs are contiguous, as is the case on amd64 and arm64,
this value is one greater than the maximum ID.   As a result, when consuming
per-CPU dtrace buffers, libdtrace tries to fetch from a non-existent CPU.  This
is mostly harmless in practice, but still wrong.

As we don't have a sysconf value for the maximum CPU ID, add a wrapper which
fetches it using the kern.smp.maxid sysctl.

MFC after:	2 weeks
Sponsored by:	Innovate UK
Differential Revision:	https://reviews.freebsd.org/D49243

(cherry picked from commit 9a30c8d347bf9aaa89277b6e5a275f737be8edce)
This commit is contained in:
Mark Johnston 2025-03-09 23:00:59 -04:00
parent 294cda7e4e
commit 0ae0226cd1
5 changed files with 23 additions and 11 deletions

View file

@ -1092,8 +1092,10 @@ dt_aggregate_go(dtrace_hdl_t *dtp)
assert(agp->dtat_ncpu == 0);
assert(agp->dtat_cpus == NULL);
agp->dtat_maxcpu = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
agp->dtat_ncpu = dt_sysconf(dtp, _SC_NPROCESSORS_MAX);
agp->dtat_maxcpu = dt_cpu_maxid(dtp) + 1;
if (agp->dtat_maxcpu <= 0)
return (-1);
agp->dtat_ncpu = dt_sysconf(dtp, _SC_NPROCESSORS_CONF);
agp->dtat_cpus = malloc(agp->dtat_ncpu * sizeof (processorid_t));
if (agp->dtat_cpus == NULL)

View file

@ -3949,8 +3949,8 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
return (rval);
}
if (max_ncpus == 0)
max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
if (max_ncpus == 0 && (max_ncpus = dt_cpu_maxid(dtp) + 1) <= 0)
return (-1);
for (i = 0; i < max_ncpus; i++) {
dtrace_bufdesc_t *nbuf;
@ -4040,8 +4040,8 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
if (!dtp->dt_active)
return (dt_set_errno(dtp, EINVAL));
if (max_ncpus == 0)
max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
if (max_ncpus == 0 && (max_ncpus = dt_cpu_maxid(dtp) + 1) <= 0)
return (-1);
if (pf == NULL)
pf = (dtrace_consume_probe_f *)dt_nullprobe;

View file

@ -620,6 +620,7 @@ extern int dt_version_defined(dt_version_t);
*/
extern char *dt_cpp_add_arg(dtrace_hdl_t *, const char *);
extern char *dt_cpp_pop_arg(dtrace_hdl_t *);
extern int dt_cpu_maxid(dtrace_hdl_t *);
#ifdef illumos
extern int dt_set_errno(dtrace_hdl_t *, int);

View file

@ -463,6 +463,20 @@ dt_cpp_pop_arg(dtrace_hdl_t *dtp)
return (arg);
}
int
dt_cpu_maxid(dtrace_hdl_t *dtp)
{
size_t len;
u_int count;
int error;
len = sizeof(count);
error = sysctlbyname("kern.smp.maxid", &count, &len, NULL, 0);
if (error != 0)
return (dt_set_errno(dtp, errno));
return (count);
}
/*PRINTFLIKE1*/
void
dt_dprintf(const char *format, ...)

View file

@ -620,11 +620,6 @@ extern int _dtrace_debug;
}
#endif
#ifndef illumos
#define _SC_CPUID_MAX _SC_NPROCESSORS_CONF
#define _SC_NPROCESSORS_MAX _SC_NPROCESSORS_CONF
#endif
/*
* Values for the dt_oformat property.
*/