diff options
author | sjg <sjg@FreeBSD.org> | 2014-04-27 08:13:43 +0000 |
---|---|---|
committer | sjg <sjg@FreeBSD.org> | 2014-04-27 08:13:43 +0000 |
commit | 0c7e03a54c8e7ddc9c3fe710f83d9ca53173692e (patch) | |
tree | b92e741b68057a24e381faa9809f32030d65574c /lib/libkvm | |
parent | c244fcbcaa61dc2a15995e7dbdf3ae8107bc2111 (diff) | |
parent | 69c3e6933b6946c49fe99b19986f018d71621980 (diff) | |
download | FreeBSD-src-0c7e03a54c8e7ddc9c3fe710f83d9ca53173692e.zip FreeBSD-src-0c7e03a54c8e7ddc9c3fe710f83d9ca53173692e.tar.gz |
Merge head
Diffstat (limited to 'lib/libkvm')
-rw-r--r-- | lib/libkvm/Makefile | 23 | ||||
-rw-r--r-- | lib/libkvm/kvm.c | 39 | ||||
-rw-r--r-- | lib/libkvm/kvm.h | 3 | ||||
-rw-r--r-- | lib/libkvm/kvm_arm.c | 6 | ||||
-rw-r--r-- | lib/libkvm/kvm_getpcpu.3 | 10 | ||||
-rw-r--r-- | lib/libkvm/kvm_ia64.c | 233 | ||||
-rw-r--r-- | lib/libkvm/kvm_minidump_amd64.c | 4 | ||||
-rw-r--r-- | lib/libkvm/kvm_minidump_arm.c | 8 | ||||
-rw-r--r-- | lib/libkvm/kvm_pcpu.c | 14 |
9 files changed, 252 insertions, 88 deletions
diff --git a/lib/libkvm/Makefile b/lib/libkvm/Makefile index f21a1bf..4608254 100644 --- a/lib/libkvm/Makefile +++ b/lib/libkvm/Makefile @@ -1,23 +1,36 @@ # @(#)Makefile 8.1 (Berkeley) 6/4/93 # $FreeBSD$ +.if defined(TARGET_ARCH) && !defined(COMPAT_32BIT) +KVM_XARCH=${TARGET_ARCH} +KVM_XCPUARCH=${KVM_XARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc64/powerpc/} +.else +KVM_XARCH=${MACHINE_ARCH} +KVM_XCPUARCH=${MACHINE_CPUARCH} +.endif + +.if ${KVM_XARCH} != ${MACHINE_ARCH} +LIB= kvm-${KVM_XARCH} +CFLAGS+=-DCROSS_LIBKVM +.else LIB= kvm +.endif + SHLIBDIR?= /lib SHLIB_MAJOR= 6 CFLAGS+=-DLIBC_SCCS -I${.CURDIR} -.if exists(${.CURDIR}/kvm_${MACHINE_ARCH}.c) -KVM_ARCH=${MACHINE_ARCH} +.if exists(${.CURDIR}/kvm_${KVM_XARCH}.c) +KVM_ARCH=${KVM_XARCH} .else -KVM_ARCH=${MACHINE_CPUARCH} +KVM_ARCH=${KVM_XCPUARCH} .endif WARNS?= 3 SRCS= kvm.c kvm_${KVM_ARCH}.c kvm_cptime.c kvm_file.c kvm_getloadavg.c \ kvm_getswapinfo.c kvm_pcpu.c kvm_proc.c kvm_vnet.c -.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" || \ - ${MACHINE_CPUARCH} == "arm" || ${MACHINE_CPUARCH} == "mips" +.if exists(${.CURDIR}/kvm_minidump_${KVM_ARCH}.c) SRCS+= kvm_minidump_${KVM_ARCH}.c .endif INCS= kvm.h diff --git a/lib/libkvm/kvm.c b/lib/libkvm/kvm.c index 9181a49..4ff62c9 100644 --- a/lib/libkvm/kvm.c +++ b/lib/libkvm/kvm.c @@ -73,9 +73,44 @@ static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; #include "kvm_private.h" +#ifndef CROSS_LIBKVM + /* from src/lib/libc/gen/nlist.c */ int __fdnlist(int, struct nlist *); +#define kvm_fdnlist __fdnlist + +#else + +#include <proc_service.h> + +static int +kvm_fdnlist(int fd, struct nlist *list) +{ + psaddr_t addr; + ps_err_e pserr; + int nfail; + + nfail = 0; + while (list->n_name != NULL && list->n_name[0] != '\0') { + list->n_other = 0; + list->n_desc = 0; + pserr = ps_pglobal_lookup(NULL, NULL, list->n_name, &addr); + if (pserr != PS_OK) { + nfail++; + list->n_value = 0; + list->n_type = 0; + } else { + list->n_value = addr; + list->n_type = N_DATA | N_EXT; + } + list++; + } + return (nfail); +} + +#endif /* CROSS_LIBKVM */ + char * kvm_geterr(kvm_t *kd) { @@ -341,7 +376,7 @@ kvm_fdnlist_prefix(kvm_t *kd, struct nlist *nl, int missing, const char *prefix, /* Do lookup on the reduced list. */ np = n; - unresolved = __fdnlist(kd->nlfd, np); + unresolved = kvm_fdnlist(kd->nlfd, np); /* Check if we could resolve further symbols and update the list. */ if (unresolved >= 0 && unresolved < missing) { @@ -398,7 +433,7 @@ _kvm_nlist(kvm_t *kd, struct nlist *nl, int initialize) * slow library call. */ if (!ISALIVE(kd)) { - error = __fdnlist(kd->nlfd, nl); + error = kvm_fdnlist(kd->nlfd, nl); if (error <= 0) /* Hard error or success. */ return (error); diff --git a/lib/libkvm/kvm.h b/lib/libkvm/kvm.h index d2ee8fa..d697795 100644 --- a/lib/libkvm/kvm.h +++ b/lib/libkvm/kvm.h @@ -77,6 +77,7 @@ char *kvm_geterr(kvm_t *); char *kvm_getfiles(kvm_t *, int, int, int *); int kvm_getloadavg(kvm_t *, double [], int); int kvm_getmaxcpu(kvm_t *); +int kvm_getncpus(kvm_t *); void *kvm_getpcpu(kvm_t *, int); uint64_t kvm_counter_u64_fetch(kvm_t *, u_long); struct kinfo_proc * @@ -88,7 +89,7 @@ kvm_t *kvm_open kvm_t *kvm_openfiles (const char *, const char *, const char *, int, char *); ssize_t kvm_read(kvm_t *, unsigned long, void *, size_t); -ssize_t kvm_read_zpcpu(kvm_t *, void *, u_long, size_t, int); +ssize_t kvm_read_zpcpu(kvm_t *, unsigned long, void *, size_t, int); ssize_t kvm_write(kvm_t *, unsigned long, const void *, size_t); __END_DECLS diff --git a/lib/libkvm/kvm_arm.c b/lib/libkvm/kvm_arm.c index b1274e9..d221f6a 100644 --- a/lib/libkvm/kvm_arm.c +++ b/lib/libkvm/kvm_arm.c @@ -42,11 +42,15 @@ __FBSDID("$FreeBSD$"); #include <sys/elf32.h> #include <sys/mman.h> +#ifndef CROSS_LIBKVM #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> - #include <machine/pmap.h> +#else +#include "../../sys/arm/include/pte.h" +#include "../../sys/arm/include/vmparam.h" +#endif #include <db.h> #include <limits.h> diff --git a/lib/libkvm/kvm_getpcpu.3 b/lib/libkvm/kvm_getpcpu.3 index 4087f1c..13192c2 100644 --- a/lib/libkvm/kvm_getpcpu.3 +++ b/lib/libkvm/kvm_getpcpu.3 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 11, 2013 +.Dd February 12, 2014 .Dt KVM_GETPCPU 3 .Os .Sh NAME @@ -47,10 +47,12 @@ .Fn kvm_dpcpu_setcpu "kvm_t *kd" "u_int cpu" .Ft int .Fn kvm_getmaxcpu "kvm_t *kd" +.Ft int +.Fn kvm_getncpus "kvm_t *kd" .Ft void * .Fn kvm_getpcpu "kvm_t *kd" "int cpu" .Ft ssize_t -.Fn kvm_read_zpcpu "kvm_t *kd" "void *buf" "u_long base" "size_t size" "int cpu" +.Fn kvm_read_zpcpu "kvm_t *kd" "u_long base" "void *buf" "size_t size" "int cpu" .Ft uint64_t .Fn kvm_counter_u64_fetch "kvm_t *kd" "u_long base" .Sh DESCRIPTION @@ -73,6 +75,10 @@ The function returns the maximum number of CPUs supported by the kernel. .Pp The +.Fn kvm_getncpus +function returns the current number of CPUs in the kernel. +.Pp +The .Fn kvm_getpcpu function returns a buffer holding the per-CPU data for a single CPU. This buffer is described by the diff --git a/lib/libkvm/kvm_ia64.c b/lib/libkvm/kvm_ia64.c index 74e2b80..5db7e1e 100644 --- a/lib/libkvm/kvm_ia64.c +++ b/lib/libkvm/kvm_ia64.c @@ -32,12 +32,21 @@ #include <sys/elf64.h> #include <sys/mman.h> +#ifndef CROSS_LIBKVM #include <machine/atomic.h> #include <machine/bootinfo.h> +#include <machine/elf.h> #include <machine/pte.h> +#else +#include "../../sys/ia64/include/atomic.h" +#include "../../sys/ia64/include/bootinfo.h" +#include "../../sys/ia64/include/elf.h" +#include "../../sys/ia64/include/pte.h" +#endif #include <kvm.h> #include <limits.h> +#include <stdint.h> #include <stdlib.h> #include <unistd.h> @@ -55,6 +64,8 @@ #define PBVM_BASE 0x9ffc000000000000UL #define PBVM_PGSZ (64 * 1024) +typedef size_t (a2p_f)(kvm_t *, uint64_t, off_t *); + struct vmstate { void *mmapbase; size_t mmapsize; @@ -62,6 +73,7 @@ struct vmstate { u_long kptdir; u_long *pbvm_pgtbl; u_int pbvm_pgtblsz; + a2p_f *kvatop; }; /* @@ -70,7 +82,7 @@ struct vmstate { * set of headers. */ static int -_kvm_maphdrs(kvm_t *kd, size_t sz) +ia64_maphdrs(kvm_t *kd, size_t sz) { struct vmstate *vm = kd->vmst; @@ -91,38 +103,103 @@ _kvm_maphdrs(kvm_t *kd, size_t sz) } /* - * Translate a physical memory address to a file-offset in the crash-dump. + * Physical core support. */ + static size_t -_kvm_pa2off(kvm_t *kd, uint64_t pa, off_t *ofs, size_t pgsz) +phys_addr2off(kvm_t *kd, uint64_t pa, off_t *ofs, size_t pgsz) { - Elf64_Ehdr *e = kd->vmst->mmapbase; - Elf64_Phdr *p = (Elf64_Phdr*)((char*)e + e->e_phoff); - int n = e->e_phnum; + Elf64_Ehdr *e; + Elf64_Phdr *p; + int n; - if (pa != REGION_ADDR(pa)) { - _kvm_err(kd, kd->program, "internal error"); - return (0); - } + if (pa != REGION_ADDR(pa)) + goto fail; + e = (Elf64_Ehdr *)(kd->vmst->mmapbase); + n = e->e_phnum; + p = (Elf64_Phdr *)(void *)((uintptr_t)(void *)e + e->e_phoff); while (n && (pa < p->p_paddr || pa >= p->p_paddr + p->p_memsz)) p++, n--; if (n == 0) - return (0); + goto fail; *ofs = (pa - p->p_paddr) + p->p_offset; if (pgsz == 0) return (p->p_memsz - (pa - p->p_paddr)); return (pgsz - ((size_t)pa & (pgsz - 1))); + + fail: + _kvm_err(kd, kd->program, "invalid physical address %#jx", + (uintmax_t)pa); + return (0); +} + +static size_t +phys_kvatop(kvm_t *kd, uint64_t va, off_t *ofs) +{ + struct ia64_lpte pte; + uint64_t pa, pgaddr, pt0addr, pt1addr; + size_t pgno, pgsz, pt0no, pt1no; + + if (va >= REGION_BASE(6)) { + /* Regions 6 and 7: direct mapped. */ + pa = REGION_ADDR(va); + return (phys_addr2off(kd, pa, ofs, 0)); + } else if (va >= REGION_BASE(5)) { + /* Region 5: Kernel Virtual Memory. */ + va = REGION_ADDR(va); + pgsz = kd->vmst->pagesize; + pt0no = KPTE_DIR0_INDEX(va, pgsz); + pt1no = KPTE_DIR1_INDEX(va, pgsz); + pgno = KPTE_PTE_INDEX(va, pgsz); + if (pt0no >= NKPTEDIR(pgsz)) + goto fail; + pt0addr = kd->vmst->kptdir + (pt0no << 3); + if (kvm_read(kd, pt0addr, &pt1addr, 8) != 8) + goto fail; + if (pt1addr == 0) + goto fail; + pt1addr += pt1no << 3; + if (kvm_read(kd, pt1addr, &pgaddr, 8) != 8) + goto fail; + if (pgaddr == 0) + goto fail; + pgaddr += pgno * sizeof(pte); + if (kvm_read(kd, pgaddr, &pte, sizeof(pte)) != sizeof(pte)) + goto fail; + if (!(pte.pte & PTE_PRESENT)) + goto fail; + pa = (pte.pte & PTE_PPN_MASK) + (va & (pgsz - 1)); + return (phys_addr2off(kd, pa, ofs, pgsz)); + } else if (va >= PBVM_BASE) { + /* Region 4: Pre-Boot Virtual Memory (PBVM). */ + va -= PBVM_BASE; + pgsz = PBVM_PGSZ; + pt0no = va / pgsz; + if (pt0no >= (kd->vmst->pbvm_pgtblsz >> 3)) + goto fail; + pt0addr = kd->vmst->pbvm_pgtbl[pt0no]; + if (!(pt0addr & PTE_PRESENT)) + goto fail; + pa = (pt0addr & PTE_PPN_MASK) + va % pgsz; + return (phys_addr2off(kd, pa, ofs, pgsz)); + } + + fail: + _kvm_err(kd, kd->program, "invalid kernel virtual address %#jx", + (uintmax_t)va); + *ofs = -1; + return (0); } static ssize_t -_kvm_read_phys(kvm_t *kd, uint64_t pa, void *buf, size_t bufsz) +phys_read(kvm_t *kd, uint64_t pa, void *buf, size_t bufsz) { off_t ofs; size_t sz; - sz = _kvm_pa2off(kd, pa, &ofs, 0); + sz = phys_addr2off(kd, pa, &ofs, 0); if (sz < bufsz) return ((ssize_t)sz); @@ -131,6 +208,50 @@ _kvm_read_phys(kvm_t *kd, uint64_t pa, void *buf, size_t bufsz) return (read(kd->pmfd, buf, bufsz)); } +/* + * Virtual core support (aka minidump). + */ + +static size_t +virt_addr2off(kvm_t *kd, uint64_t va, off_t *ofs, size_t pgsz) +{ + Elf64_Ehdr *e; + Elf64_Phdr *p; + int n; + + if (va < REGION_BASE(4)) + goto fail; + + e = (Elf64_Ehdr *)(kd->vmst->mmapbase); + n = e->e_phnum; + p = (Elf64_Phdr *)(void *)((uintptr_t)(void *)e + e->e_phoff); + while (n && (va < p->p_vaddr || va >= p->p_vaddr + p->p_memsz)) + p++, n--; + if (n == 0) + goto fail; + + *ofs = (va - p->p_vaddr) + p->p_offset; + if (pgsz == 0) + return (p->p_memsz - (va - p->p_vaddr)); + return (pgsz - ((size_t)va & (pgsz - 1))); + + fail: + _kvm_err(kd, kd->program, "invalid virtual address %#jx", + (uintmax_t)va); + return (0); +} + +static size_t +virt_kvatop(kvm_t *kd, uint64_t va, off_t *ofs) +{ + + return (virt_addr2off(kd, va, ofs, 0)); +} + +/* + * KVM architecture support functions. + */ + void _kvm_freevtop(kvm_t *kd) { @@ -160,27 +281,37 @@ _kvm_initvtop(kvm_t *kd) return (-1); } +#ifndef CROSS_LIBKVM kd->vmst->pagesize = getpagesize(); +#else + kd->vmst->pagesize = 8192; +#endif - if (_kvm_maphdrs(kd, sizeof(Elf64_Ehdr)) == -1) + if (ia64_maphdrs(kd, sizeof(Elf64_Ehdr)) == -1) return (-1); ehdr = kd->vmst->mmapbase; hdrsz = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum; - if (_kvm_maphdrs(kd, hdrsz) == -1) + if (ia64_maphdrs(kd, hdrsz) == -1) return (-1); + kd->vmst->kvatop = (ehdr->e_flags & EF_IA_64_ABSOLUTE) ? + phys_kvatop : virt_kvatop; + /* * Load the PBVM page table. We need this to resolve PBVM addresses. * The PBVM page table is obtained from the bootinfo structure, of - * which the physical address is given to us in e_entry. If e_entry - * is 0, then this is assumed to be a pre-PBVM kernel. + * which the address is given to us in e_entry. If e_entry is 0, then + * this is assumed to be a pre-PBVM kernel. + * Note that the address of the bootinfo structure is either physical + * or virtual, depending on whether the core is physical or virtual. */ - if (ehdr->e_entry != 0) { - sz = _kvm_read_phys(kd, ehdr->e_entry, &bi, sizeof(bi)); + if (ehdr->e_entry != 0 && (ehdr->e_flags & EF_IA_64_ABSOLUTE) != 0) { + sz = phys_read(kd, ehdr->e_entry, &bi, sizeof(bi)); if (sz != sizeof(bi)) { _kvm_err(kd, kd->program, - "cannot read bootinfo from PA %#lx", ehdr->e_entry); + "cannot read bootinfo at physical address %#jx", + (uintmax_t)ehdr->e_entry); return (-1); } if (bi.bi_magic != BOOTINFO_MAGIC) { @@ -193,12 +324,12 @@ _kvm_initvtop(kvm_t *kd) return (-1); } kd->vmst->pbvm_pgtblsz = bi.bi_pbvm_pgtblsz; - sz = _kvm_read_phys(kd, bi.bi_pbvm_pgtbl, kd->vmst->pbvm_pgtbl, + sz = phys_read(kd, bi.bi_pbvm_pgtbl, kd->vmst->pbvm_pgtbl, bi.bi_pbvm_pgtblsz); if (sz != bi.bi_pbvm_pgtblsz) { _kvm_err(kd, kd->program, - "cannot read page table from PA %#lx", - bi.bi_pbvm_pgtbl); + "cannot read page table at physical address %#jx", + (uintmax_t)bi.bi_pbvm_pgtbl); return (-1); } } else { @@ -225,7 +356,7 @@ _kvm_initvtop(kvm_t *kd) return (-1); } - if (va < REGION_BASE(6)) { + if (va == REGION_BASE(5)) { _kvm_err(kd, kd->program, "kptdir is itself virtual"); return (-1); } @@ -237,56 +368,8 @@ _kvm_initvtop(kvm_t *kd) int _kvm_kvatop(kvm_t *kd, u_long va, off_t *ofs) { - struct ia64_lpte pte; - uint64_t pa, pgaddr, pt0addr, pt1addr; - size_t pgno, pgsz, pt0no, pt1no; - - if (va >= REGION_BASE(6)) { - /* Regions 6 and 7: direct mapped. */ - pa = REGION_ADDR(va); - return (_kvm_pa2off(kd, pa, ofs, 0)); - } else if (va >= REGION_BASE(5)) { - /* Region 5: Kernel Virtual Memory. */ - va = REGION_ADDR(va); - pgsz = kd->vmst->pagesize; - pt0no = KPTE_DIR0_INDEX(va, pgsz); - pt1no = KPTE_DIR1_INDEX(va, pgsz); - pgno = KPTE_PTE_INDEX(va, pgsz); - if (pt0no >= NKPTEDIR(pgsz)) - goto fail; - pt0addr = kd->vmst->kptdir + (pt0no << 3); - if (kvm_read(kd, pt0addr, &pt1addr, 8) != 8) - goto fail; - if (pt1addr == 0) - goto fail; - pt1addr += pt1no << 3; - if (kvm_read(kd, pt1addr, &pgaddr, 8) != 8) - goto fail; - if (pgaddr == 0) - goto fail; - pgaddr += pgno * sizeof(pte); - if (kvm_read(kd, pgaddr, &pte, sizeof(pte)) != sizeof(pte)) - goto fail; - if (!(pte.pte & PTE_PRESENT)) - goto fail; - pa = (pte.pte & PTE_PPN_MASK) + (va & (pgsz - 1)); - return (_kvm_pa2off(kd, pa, ofs, pgsz)); - } else if (va >= PBVM_BASE) { - /* Region 4: Pre-Boot Virtual Memory (PBVM). */ - va -= PBVM_BASE; - pgsz = PBVM_PGSZ; - pt0no = va / pgsz; - if (pt0no >= (kd->vmst->pbvm_pgtblsz >> 3)) - goto fail; - pt0addr = kd->vmst->pbvm_pgtbl[pt0no]; - if (!(pt0addr & PTE_PRESENT)) - goto fail; - pa = (pt0addr & PTE_PPN_MASK) + va % pgsz; - return (_kvm_pa2off(kd, pa, ofs, pgsz)); - } + size_t sz; - fail: - _kvm_err(kd, kd->program, "invalid kernel virtual address"); - *ofs = ~0UL; - return (0); + sz = kd->vmst->kvatop(kd, va, ofs); + return ((sz > INT_MAX) ? INT_MAX : sz); } diff --git a/lib/libkvm/kvm_minidump_amd64.c b/lib/libkvm/kvm_minidump_amd64.c index 8d31673..779fa97 100644 --- a/lib/libkvm/kvm_minidump_amd64.c +++ b/lib/libkvm/kvm_minidump_amd64.c @@ -214,6 +214,8 @@ _kvm_minidump_vatop_v1(kvm_t *kd, u_long va, off_t *pa) if (va >= vm->hdr.kernbase) { pteindex = (va - vm->hdr.kernbase) >> PAGE_SHIFT; + if (pteindex >= vm->hdr.pmapsize / sizeof(*vm->page_map)) + goto invalid; pte = vm->page_map[pteindex]; if (((u_long)pte & PG_V) == 0) { _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid"); @@ -264,6 +266,8 @@ _kvm_minidump_vatop(kvm_t *kd, u_long va, off_t *pa) if (va >= vm->hdr.kernbase) { pdeindex = (va - vm->hdr.kernbase) >> PDRSHIFT; + if (pdeindex >= vm->hdr.pmapsize / sizeof(*vm->page_map)) + goto invalid; pde = vm->page_map[pdeindex]; if (((u_long)pde & PG_V) == 0) { _kvm_err(kd, kd->program, "_kvm_vatop: pde not valid"); diff --git a/lib/libkvm/kvm_minidump_arm.c b/lib/libkvm/kvm_minidump_arm.c index f6147d0..f4ba604 100644 --- a/lib/libkvm/kvm_minidump_arm.c +++ b/lib/libkvm/kvm_minidump_arm.c @@ -34,7 +34,9 @@ __FBSDID("$FreeBSD$"); */ #include <sys/param.h> +#ifndef CROSS_LIBKVM #include <sys/user.h> +#endif #include <sys/proc.h> #include <sys/stat.h> #include <sys/mman.h> @@ -45,12 +47,18 @@ __FBSDID("$FreeBSD$"); #include <nlist.h> #include <kvm.h> +#ifndef CROSS_LIBKVM #include <vm/vm.h> #include <vm/vm_param.h> #include <machine/elf.h> #include <machine/cpufunc.h> #include <machine/minidump.h> +#else +#include "../../sys/arm/include/pte.h" +#include "../../sys/arm/include/vmparam.h" +#include "../../sys/arm/include/minidump.h" +#endif #include <limits.h> diff --git a/lib/libkvm/kvm_pcpu.c b/lib/libkvm/kvm_pcpu.c index 2d7fb41..662566a 100644 --- a/lib/libkvm/kvm_pcpu.c +++ b/lib/libkvm/kvm_pcpu.c @@ -173,6 +173,16 @@ kvm_getmaxcpu(kvm_t *kd) return (maxcpu); } +int +kvm_getncpus(kvm_t *kd) +{ + + if (mp_ncpus == 0) + if (_kvm_pcpu_init(kd) < 0) + return (-1); + return (mp_ncpus); +} + static int _kvm_dpcpu_setcpu(kvm_t *kd, u_int cpu, int report_error) { @@ -306,7 +316,7 @@ kvm_dpcpu_setcpu(kvm_t *kd, u_int cpu) * 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) +kvm_read_zpcpu(kvm_t *kd, u_long base, void *buf, size_t size, int cpu) { return (kvm_read(kd, (uintptr_t)(base + sizeof(struct pcpu) * cpu), @@ -327,7 +337,7 @@ kvm_counter_u64_fetch(kvm_t *kd, u_long base) r = 0; for (int i = 0; i < mp_ncpus; i++) { - if (kvm_read_zpcpu(kd, &c, base, sizeof(c), i) != sizeof(c)) + if (kvm_read_zpcpu(kd, base, &c, sizeof(c), i) != sizeof(c)) return (0); r += c; } |