From 147dda2e5e80203cec822fed13a97e3e1531cbaf Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 10 Apr 2013 20:26:53 +0000 Subject: o Provide function kvm_read_zpcpu() to access UMA_ZONE_PCPU allocations. o Provide function kvm_counter_u64_fetch() to fetch valut of a counter(9). Sponsored by: Nginx, Inc. --- lib/libkvm/kvm_pcpu.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'lib/libkvm/kvm_pcpu.c') diff --git a/lib/libkvm/kvm_pcpu.c b/lib/libkvm/kvm_pcpu.c index d7108b4..2d7fb41 100644 --- a/lib/libkvm/kvm_pcpu.c +++ b/lib/libkvm/kvm_pcpu.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2013 Gleb Smirnoff * Copyright (c) 2010 Juniper Networks, Inc. * Copyright (c) 2009 Robert N. M. Watson * Copyright (c) 2009 Bjoern A. Zeeb @@ -50,8 +51,12 @@ __FBSDID("$FreeBSD$"); static struct nlist kvm_pcpu_nl[] = { { .n_name = "_cpuid_to_pcpu" }, { .n_name = "_mp_maxcpus" }, + { .n_name = "_mp_ncpus" }, { .n_name = NULL }, }; +#define NL_CPUID_TO_PCPU 0 +#define NL_MP_MAXCPUS 1 +#define NL_MP_NCPUS 2 /* * Kernel per-CPU data state. We cache this stuff on the first @@ -63,9 +68,7 @@ static struct nlist kvm_pcpu_nl[] = { */ static void **pcpu_data; static int maxcpu; - -#define NL_CPUID_TO_PCPU 0 -#define NL_MP_MAXCPUS 1 +static int mp_ncpus; static int _kvm_pcpu_init(kvm_t *kd) @@ -89,6 +92,15 @@ _kvm_pcpu_init(kvm_t *kd) _kvm_err(kd, kd->program, "cannot read mp_maxcpus"); return (-1); } + if (kvm_pcpu_nl[NL_MP_NCPUS].n_value == 0) { + _kvm_err(kd, kd->program, "unable to find mp_ncpus"); + return (-1); + } + if (kvm_read(kd, kvm_pcpu_nl[NL_MP_NCPUS].n_value, &mp_ncpus, + sizeof(mp_ncpus)) != sizeof(mp_ncpus)) { + _kvm_err(kd, kd->program, "cannot read mp_ncpus"); + return (-1); + } len = max * sizeof(void *); data = malloc(len); if (data == NULL) { @@ -289,3 +301,36 @@ kvm_dpcpu_setcpu(kvm_t *kd, u_int cpu) return (_kvm_dpcpu_setcpu(kd, cpu, 1)); } + +/* + * Obtain a per-CPU copy for given cpu from UMA_ZONE_PCPU allocation. + */ +ssize_t +kvm_read_zpcpu(kvm_t *kd, void *buf, u_long base, size_t size, int cpu) +{ + + return (kvm_read(kd, (uintptr_t)(base + sizeof(struct pcpu) * cpu), + buf, size)); +} + +/* + * Fetch value of a counter(9). + */ +uint64_t +kvm_counter_u64_fetch(kvm_t *kd, u_long base) +{ + uint64_t r, c; + + if (mp_ncpus == 0) + if (_kvm_pcpu_init(kd) < 0) + return (0); + + r = 0; + for (int i = 0; i < mp_ncpus; i++) { + if (kvm_read_zpcpu(kd, &c, base, sizeof(c), i) != sizeof(c)) + return (0); + r += c; + } + + return (r); +} -- cgit v1.1