code:
/*-
 * Copyright (c) 1982, 1986, 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)param.h	8.3 (Berkeley) 4/4/95
 * $FreeBSD: release/9.0.0/sys/sys/param.h 226199 2011-10-10 12:07:04Z kib $
 */

#ifndef _SYS_PARAM_H_
#define _SYS_PARAM_H_

#include <sys/_null.h>

#define	BSD	199506		/* System version (year & month). */
#define BSD4_3	1
#define BSD4_4	1

/*
 * __FreeBSD_version numbers are documented in the Porter's Handbook.
 * If you bump the version for any reason, you should update the documentation
 * there.
 * Currently this lives here:
 *
 *	doc/en_US.ISO8859-1/books/porters-handbook/book.sgml
 *
 * scheme is:  <major><two digit minor>Rxx
 *		'R' is in the range 0 to 4 if this is a release branch or
 *		x.0-CURRENT before RELENG_*_0 is created, otherwise 'R' is
 *		in the range 5 to 9.
 */
#undef __FreeBSD_version
#define __FreeBSD_version 900044	/* Master, propagated to newvers */

#ifdef _KERNEL
#define	P_OSREL_SIGWAIT		700000
#define	P_OSREL_SIGSEGV		700004
#define	P_OSREL_MAP_ANON	800104
#endif

#ifndef LOCORE
#include <sys/types.h>
#endif

/*
 * Machine-independent constants (some used in following include files).
 * Redefined constants are from POSIX 1003.1 limits file.
 *
 * MAXCOMLEN should be >= sizeof(ac_comm) (see <acct.h>)
 */
#include <sys/syslimits.h>

#define	MAXCOMLEN	19		/* max command name remembered */
#define	MAXINTERP	PATH_MAX	/* max interpreter file name length */
#define	MAXLOGNAME	17		/* max login name length (incl. NUL) */
#define	MAXUPRC		CHILD_MAX	/* max simultaneous processes */
#define	NCARGS		ARG_MAX		/* max bytes for an exec function */
#define	NGROUPS		(NGROUPS_MAX+1)	/* max number groups */
#define	NOFILE		OPEN_MAX	/* max open files per process */
#define	NOGROUP		65535		/* marker for empty group set member */
#define MAXHOSTNAMELEN	256		/* max hostname size */
#define SPECNAMELEN	63		/* max length of devicename */

/* More types and definitions used throughout the kernel. */
#ifdef _KERNEL
#include <sys/cdefs.h>
#include <sys/errno.h>
#ifndef LOCORE
#include <sys/time.h>
#include <sys/priority.h>
#endif

#ifndef FALSE
#define	FALSE	0
#endif
#ifndef TRUE
#define	TRUE	1
#endif
#endif

#ifndef _KERNEL
/* Signals. */
#include <sys/signal.h>
#endif

/* Machine type dependent parameters. */
#include <machine/param.h>
#ifndef _KERNEL
#include <sys/limits.h>
#endif

#ifndef DEV_BSHIFT
#define	DEV_BSHIFT	9		/* log2(DEV_BSIZE) */
#endif
#define	DEV_BSIZE	(1<<DEV_BSHIFT)

#ifndef BLKDEV_IOSIZE
#define BLKDEV_IOSIZE  PAGE_SIZE	/* default block device I/O size */
#endif
#ifndef DFLTPHYS
#define DFLTPHYS	(64 * 1024)	/* default max raw I/O transfer size */
#endif
#ifndef MAXPHYS
#define MAXPHYS		(128 * 1024)	/* max raw I/O transfer size */
#endif
#ifndef MAXDUMPPGS
#define MAXDUMPPGS	(DFLTPHYS/PAGE_SIZE)
#endif

/*
 * Constants related to network buffer management.
 * MCLBYTES must be no larger than PAGE_SIZE.
 */
#ifndef	MSIZE
#define MSIZE		256		/* size of an mbuf */
#endif	/* MSIZE */

#ifndef	MCLSHIFT
#define MCLSHIFT	11		/* convert bytes to mbuf clusters */
#endif	/* MCLSHIFT */

#define MCLBYTES	(1 << MCLSHIFT)	/* size of an mbuf cluster */

#if PAGE_SIZE < 2048
#define	MJUMPAGESIZE	MCLBYTES
#elif PAGE_SIZE <= 8192
#define	MJUMPAGESIZE	PAGE_SIZE
#else
#define	MJUMPAGESIZE	(8 * 1024)
#endif

#define	MJUM9BYTES	(9 * 1024)	/* jumbo cluster 9k */
#define	MJUM16BYTES	(16 * 1024)	/* jumbo cluster 16k */

/*
 * Some macros for units conversion
 */

/* clicks to bytes */
#ifndef ctob
#define ctob(x)	((x)<<PAGE_SHIFT)
#endif

/* bytes to clicks */
#ifndef btoc
#define btoc(x)	(((vm_offset_t)(x)+PAGE_MASK)>>PAGE_SHIFT)
#endif

/*
 * btodb() is messy and perhaps slow because `bytes' may be an off_t.  We
 * want to shift an unsigned type to avoid sign extension and we don't
 * want to widen `bytes' unnecessarily.  Assume that the result fits in
 * a daddr_t.
 */
#ifndef btodb
#define btodb(bytes)	 		/* calculates (bytes / DEV_BSIZE) */ \
	(sizeof (bytes) > sizeof(long) \
	 ? (daddr_t)((unsigned long long)(bytes) >> DEV_BSHIFT) \
	 : (daddr_t)((unsigned long)(bytes) >> DEV_BSHIFT))
#endif

#ifndef dbtob
#define dbtob(db)			/* calculates (db * DEV_BSIZE) */ \
	((off_t)(db) << DEV_BSHIFT)
#endif

#define	PRIMASK	0x0ff
#define	PCATCH	0x100		/* OR'd with pri for tsleep to check signals */
#define	PDROP	0x200	/* OR'd with pri to stop re-entry of interlock mutex */
#define	PBDRY	0x400	/* for PCATCH stop is done on the user boundary */

#define	NZERO	0		/* default "nice" */

#define	NBBY	8		/* number of bits in a byte */
#define	NBPW	sizeof(int)	/* number of bytes per word (integer) */

#define	CMASK	022		/* default file mask: S_IWGRP|S_IWOTH */

#define	NODEV	(dev_t)(-1)	/* non-existent device */

/*
 * File system parameters and macros.
 *
 * MAXBSIZE -	Filesystems are made out of blocks of at most MAXBSIZE bytes
 *		per block.  MAXBSIZE may be made larger without effecting
 *		any existing filesystems as long as it does not exceed MAXPHYS,
 *		and may be made smaller at the risk of not being able to use
 *		filesystems which require a block size exceeding MAXBSIZE.
 *
 * BKVASIZE -	Nominal buffer space per buffer, in bytes.  BKVASIZE is the
 *		minimum KVM memory reservation the kernel is willing to make.
 *		Filesystems can of course request smaller chunks.  Actual
 *		backing memory uses a chunk size of a page (PAGE_SIZE).
 *
 *		If you make BKVASIZE too small you risk seriously fragmenting
 *		the buffer KVM map which may slow things down a bit.  If you
 *		make it too big the kernel will not be able to optimally use
 *		the KVM memory reserved for the buffer cache and will wind
 *		up with too-few buffers.
 *
 *		The default is 16384, roughly 2x the block size used by a
 *		normal UFS filesystem.
 */
#define MAXBSIZE	65536	/* must be power of 2 */
#define BKVASIZE	16384	/* must be power of 2 */
#define BKVAMASK	(BKVASIZE-1)

/*
 * MAXPATHLEN defines the longest permissible path length after expanding
 * symbolic links. It is used to allocate a temporary buffer from the buffer
 * pool in which to do the name expansion, hence should be a power of two,
 * and must be less than or equal to MAXBSIZE.  MAXSYMLINKS defines the
 * maximum number of symbolic links that may be expanded in a path name.
 * It should be set high enough to allow all legitimate uses, but halt
 * infinite loops reasonably quickly.
 */
#define	MAXPATHLEN	PATH_MAX
#define MAXSYMLINKS	32

/* Bit map related macros. */
#define	setbit(a,i)	(((unsigned char *)(a))[(i)/NBBY] |= 1<<((i)%NBBY))
#define	clrbit(a,i)	(((unsigned char *)(a))[(i)/NBBY] &= ~(1<<((i)%NBBY)))
#define	isset(a,i)							\
	(((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY)))
#define	isclr(a,i)							\
	((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0)

/* Macros for counting and rounding. */
#ifndef howmany
#define	howmany(x, y)	(((x)+((y)-1))/(y))
#endif
#define	rounddown(x, y)	(((x)/(y))*(y))
#define	roundup(x, y)	((((x)+((y)-1))/(y))*(y))  /* to any y */
#define	roundup2(x, y)	(((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
#define powerof2(x)	((((x)-1)&(x))==0)

/* Macros for min/max. */
#define	MIN(a,b) (((a)<(b))?(a):(b))
#define	MAX(a,b) (((a)>(b))?(a):(b))

#ifdef _KERNEL
/*
 * Basic byte order function prototypes for non-inline functions.
 */
#ifndef LOCORE
#ifndef _BYTEORDER_PROTOTYPED
#define	_BYTEORDER_PROTOTYPED
__BEGIN_DECLS
__uint32_t	 htonl(__uint32_t);
__uint16_t	 htons(__uint16_t);
__uint32_t	 ntohl(__uint32_t);
__uint16_t	 ntohs(__uint16_t);
__END_DECLS
#endif
#endif

#ifndef lint
#ifndef _BYTEORDER_FUNC_DEFINED
#define	_BYTEORDER_FUNC_DEFINED
#define	htonl(x)	__htonl(x)
#define	htons(x)	__htons(x)
#define	ntohl(x)	__ntohl(x)
#define	ntohs(x)	__ntohs(x)
#endif /* !_BYTEORDER_FUNC_DEFINED */
#endif /* lint */
#endif /* _KERNEL */

/*
 * Scale factor for scaled integers used to count %cpu time and load avgs.
 *
 * The number of CPU `tick's that map to a unique `%age' can be expressed
 * by the formula (1 / (2 ^ (FSHIFT - 11))).  The maximum load average that
 * can be calculated (assuming 32 bits) can be closely approximated using
 * the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15).
 *
 * For the scheduler to maintain a 1:1 mapping of CPU `tick' to `%age',
 * FSHIFT must be at least 11; this gives us a maximum load avg of ~1024.
 */
#define	FSHIFT	11		/* bits to right of fixed binary point */
#define FSCALE	(1<<FSHIFT)

#define dbtoc(db)			/* calculates devblks to pages */ \
	((db + (ctodb(1) - 1)) >> (PAGE_SHIFT - DEV_BSHIFT))

#define ctodb(db)			/* calculates pages to devblks */ \
	((db) << (PAGE_SHIFT - DEV_BSHIFT))

/*
 * Given the pointer x to the member m of the struct s, return
 * a pointer to the containing structure.
 */
#define	member2struct(s, m, x)						\
	((struct s *)(void *)((char *)(x) - offsetof(struct s, m)))

/*
 * Access a variable length array that has been declared as a fixed
 * length array.
 */
#define __PAST_END(array, offset) (((typeof(*(array)) *)(array))[offset])

#endif	/* _SYS_PARAM_H_ */


code:
/*-
 * Copyright (c) 1997, Stefan Esser <se@FreeBSD.ORG>
 * Copyright (c) 1997, 1998, 1999, Kenneth D. Merry <ken@FreeBSD.ORG>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *	$FreeBSD: release/9.0.0/sys/sys/pciio.h 188032 2009-02-02 22:04:40Z jhb $
 *
 */

#ifndef _SYS_PCIIO_H_
#define	_SYS_PCIIO_H_

#include <sys/ioccom.h>

#define PCI_MAXNAMELEN	16

typedef enum {
	PCI_GETCONF_LAST_DEVICE,
	PCI_GETCONF_LIST_CHANGED,
	PCI_GETCONF_MORE_DEVS,
	PCI_GETCONF_ERROR
} pci_getconf_status;

typedef enum {
	PCI_GETCONF_NO_MATCH		= 0x0000,
	PCI_GETCONF_MATCH_DOMAIN	= 0x0001,
	PCI_GETCONF_MATCH_BUS		= 0x0002,
	PCI_GETCONF_MATCH_DEV		= 0x0004,
	PCI_GETCONF_MATCH_FUNC		= 0x0008,
	PCI_GETCONF_MATCH_NAME		= 0x0010,
	PCI_GETCONF_MATCH_UNIT		= 0x0020,
	PCI_GETCONF_MATCH_VENDOR	= 0x0040,
	PCI_GETCONF_MATCH_DEVICE	= 0x0080,
	PCI_GETCONF_MATCH_CLASS		= 0x0100
} pci_getconf_flags;

struct pcisel {
	u_int32_t	pc_domain;	/* domain number */
	u_int8_t	pc_bus;		/* bus number */
	u_int8_t	pc_dev;		/* device on this bus */
	u_int8_t	pc_func;	/* function on this device */
};

struct pci_conf {
	struct pcisel	pc_sel;		/* domain+bus+slot+function */
	u_int8_t	pc_hdr;		/* PCI header type */
	u_int16_t	pc_subvendor;	/* card vendor ID */
	u_int16_t	pc_subdevice;	/* card device ID, assigned by
					   card vendor */
	u_int16_t	pc_vendor;	/* chip vendor ID */
	u_int16_t	pc_device;	/* chip device ID, assigned by
					   chip vendor */
	u_int8_t	pc_class;	/* chip PCI class */
	u_int8_t	pc_subclass;	/* chip PCI subclass */
	u_int8_t	pc_progif;	/* chip PCI programming interface */
	u_int8_t	pc_revid;	/* chip revision ID */
	char		pd_name[PCI_MAXNAMELEN + 1];  /* device name */
	u_long		pd_unit;	/* device unit number */
};

struct pci_match_conf {
	struct pcisel		pc_sel;		/* domain+bus+slot+function */
	char			pd_name[PCI_MAXNAMELEN + 1];  /* device name */
	u_long			pd_unit;	/* Unit number */
	u_int16_t		pc_vendor;	/* PCI Vendor ID */
	u_int16_t		pc_device;	/* PCI Device ID */
	u_int8_t		pc_class;	/* PCI class */
	pci_getconf_flags	flags;		/* Matching expression */
};

struct pci_conf_io {
	u_int32_t		pat_buf_len;	/* pattern buffer length */
	u_int32_t		num_patterns;	/* number of patterns */
	struct pci_match_conf	*patterns;	/* pattern buffer */
	u_int32_t		match_buf_len;	/* match buffer length */
	u_int32_t		num_matches;	/* number of matches returned */
	struct pci_conf		*matches;	/* match buffer */
	u_int32_t		offset;		/* offset into device list */
	u_int32_t		generation;	/* device list generation */
	pci_getconf_status	status;		/* request status */
};

struct pci_io {
	struct pcisel	pi_sel;		/* device to operate on */
	int		pi_reg;		/* configuration register to examine */
	int		pi_width;	/* width (in bytes) of read or write */
	u_int32_t	pi_data;	/* data to write or result of read */
};

struct pci_bar_io {
	struct pcisel	pbi_sel;	/* device to operate on */
	int		pbi_reg;	/* starting address of BAR */
	int		pbi_enabled;	/* decoding enabled */
	uint64_t	pbi_base;	/* current value of BAR */
	uint64_t	pbi_length;	/* length of BAR */
};

#define	PCIOCGETCONF	_IOWR('p', 5, struct pci_conf_io)
#define	PCIOCREAD	_IOWR('p', 2, struct pci_io)
#define	PCIOCWRITE	_IOWR('p', 3, struct pci_io)
#define	PCIOCATTACHED	_IOWR('p', 4, struct pci_io)
#define	PCIOCGETBAR	_IOWR('p', 6, struct pci_bar_io)

#endif /* !_SYS_PCIIO_H_ */

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (c) 2001 Wind River Systems, Inc.
 * All rights reserved.
 * Written by: John Baldwin <jhb@FreeBSD.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/pcpu.h 224221 2011-07-19 16:50:55Z attilio $
 */

#ifndef _SYS_PCPU_H_
#define	_SYS_PCPU_H_

#ifdef LOCORE
#error "no assembler-serviceable parts inside"
#endif

#include <sys/_cpuset.h>
#include <sys/queue.h>
#include <sys/vmmeter.h>
#include <sys/resource.h>
#include <machine/pcpu.h>

#define	DPCPU_SETNAME		"set_pcpu"
#define	DPCPU_SYMPREFIX		"pcpu_entry_"

#ifdef _KERNEL

/*
 * Define a set for pcpu data.
 */
extern uintptr_t *__start_set_pcpu;
__GLOBL(__start_set_pcpu);
extern uintptr_t *__stop_set_pcpu;
__GLOBL(__stop_set_pcpu);

/*
 * Array of dynamic pcpu base offsets.  Indexed by id.
 */
extern uintptr_t dpcpu_off[];

/*
 * Convenience defines.
 */
#define	DPCPU_START		((uintptr_t)&__start_set_pcpu)
#define	DPCPU_STOP		((uintptr_t)&__stop_set_pcpu)
#define	DPCPU_BYTES		(DPCPU_STOP - DPCPU_START)
#define	DPCPU_MODMIN		2048
#define	DPCPU_SIZE		roundup2(DPCPU_BYTES, PAGE_SIZE)
#define	DPCPU_MODSIZE		(DPCPU_SIZE - (DPCPU_BYTES - DPCPU_MODMIN))

/*
 * Declaration and definition.
 */
#define	DPCPU_NAME(n)		pcpu_entry_##n
#define	DPCPU_DECLARE(t, n)	extern t DPCPU_NAME(n)
#define	DPCPU_DEFINE(t, n)	t DPCPU_NAME(n) __section(DPCPU_SETNAME) __used

/*
 * Accessors with a given base.
 */
#define	_DPCPU_PTR(b, n)						\
    (__typeof(DPCPU_NAME(n))*)((b) + (uintptr_t)&DPCPU_NAME(n))
#define	_DPCPU_GET(b, n)	(*_DPCPU_PTR(b, n))
#define	_DPCPU_SET(b, n, v)	(*_DPCPU_PTR(b, n) = v)

/*
 * Accessors for the current cpu.
 */
#define	DPCPU_PTR(n)		_DPCPU_PTR(PCPU_GET(dynamic), n)
#define	DPCPU_GET(n)		(*DPCPU_PTR(n))
#define	DPCPU_SET(n, v)		(*DPCPU_PTR(n) = v)

/*
 * Accessors for remote cpus.
 */
#define	DPCPU_ID_PTR(i, n)	_DPCPU_PTR(dpcpu_off[(i)], n)
#define	DPCPU_ID_GET(i, n)	(*DPCPU_ID_PTR(i, n))
#define	DPCPU_ID_SET(i, n, v)	(*DPCPU_ID_PTR(i, n) = v)

/*
 * Utility macros.
 */
#define	DPCPU_SUM(n) __extension__					\
({									\
	u_int _i;							\
	__typeof(*DPCPU_PTR(n)) sum;					\
									\
	sum = 0;							\
	CPU_FOREACH(_i) {						\
		sum += *DPCPU_ID_PTR(_i, n);				\
	}								\
	sum;								\
})

#define	DPCPU_VARSUM(n, var) __extension__				\
({									\
	u_int _i;							\
	__typeof((DPCPU_PTR(n))->var) sum;				\
									\
	sum = 0;							\
	CPU_FOREACH(_i) {						\
		sum += (DPCPU_ID_PTR(_i, n))->var;			\
	}								\
	sum;								\
})

#define	DPCPU_ZERO(n) do {						\
	u_int _i;							\
									\
	CPU_FOREACH(_i) {						\
		bzero(DPCPU_ID_PTR(_i, n), sizeof(*DPCPU_PTR(n)));	\
	}								\
} while(0)

#endif /* _KERNEL */

/*
 * XXXUPS remove as soon as we have per cpu variable
 * linker sets and can define rm_queue in _rm_lock.h
 */
struct rm_queue {
	struct rm_queue* volatile rmq_next;
	struct rm_queue* volatile rmq_prev;
};

/*
 * This structure maps out the global data that needs to be kept on a
 * per-cpu basis.  The members are accessed via the PCPU_GET/SET/PTR
 * macros defined in <machine/pcpu.h>.  Machine dependent fields are
 * defined in the PCPU_MD_FIELDS macro defined in <machine/pcpu.h>.
 */
struct pcpu {
	struct thread	*pc_curthread;		/* Current thread */
	struct thread	*pc_idlethread;		/* Idle thread */
	struct thread	*pc_fpcurthread;	/* Fp state owner */
	struct thread	*pc_deadthread;		/* Zombie thread or NULL */
	struct pcb	*pc_curpcb;		/* Current pcb */
	uint64_t	pc_switchtime;		/* cpu_ticks() at last csw */
	int		pc_switchticks;		/* `ticks' at last csw */
	u_int		pc_cpuid;		/* This cpu number */
	STAILQ_ENTRY(pcpu) pc_allcpu;
	struct lock_list_entry *pc_spinlocks;
	struct vmmeter	pc_cnt;			/* VM stats counters */
	long		pc_cp_time[CPUSTATES];	/* statclock ticks */
	struct device	*pc_device;
	void		*pc_netisr;		/* netisr SWI cookie */
	int		pc_dnweight;		/* vm_page_dontneed() */
	int		pc_domain;		/* Memory domain. */

	/*
	 * Stuff for read mostly lock
	 *
	 * XXXUPS remove as soon as we have per cpu variable
	 * linker sets.
	 */
	struct rm_queue	pc_rm_queue;

	uintptr_t	pc_dynamic;		/* Dynamic per-cpu data area */

	/*
	 * Keep MD fields last, so that CPU-specific variations on a
	 * single architecture don't result in offset variations of
	 * the machine-independent fields of the pcpu.  Even though
	 * the pcpu structure is private to the kernel, some ports
	 * (e.g., lsof, part of gtop) define _KERNEL and include this
	 * header.  While strictly speaking this is wrong, there's no
	 * reason not to keep the offsets of the MI fields constant
	 * if only to make kernel debugging easier.
	 */
	PCPU_MD_FIELDS;
} __aligned(CACHE_LINE_SIZE);

#ifdef _KERNEL

STAILQ_HEAD(cpuhead, pcpu);

extern struct cpuhead cpuhead;
extern struct pcpu *cpuid_to_pcpu[];

#define	curcpu		PCPU_GET(cpuid)
#define	curproc		(curthread->td_proc)
#ifndef curthread
#define	curthread	PCPU_GET(curthread)
#endif
#define	curvidata	PCPU_GET(vidata)

/*
 * Machine dependent callouts.  cpu_pcpu_init() is responsible for
 * initializing machine dependent fields of struct pcpu, and
 * db_show_mdpcpu() is responsible for handling machine dependent
 * fields for the DDB 'show pcpu' command.
 */
void	cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size);
void	db_show_mdpcpu(struct pcpu *pcpu);

void	*dpcpu_alloc(int size);
void	dpcpu_copy(void *s, int size);
void	dpcpu_free(void *s, int size);
void	dpcpu_init(void *dpcpu, int cpuid);
void	pcpu_destroy(struct pcpu *pcpu);
struct	pcpu *pcpu_find(u_int cpuid);
void	pcpu_init(struct pcpu *pcpu, int cpuid, size_t size);

#endif /* _KERNEL */

#endif /* !_SYS_PCPU_H_ */


code:
/*-
 * Copyright 1997 Sean Eric Fagan
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Sean Eric Fagan
 * 4. Neither the name of the author may be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

/*
 * procfs ioctl definitions.
 *
 * $FreeBSD: release/9.0.0/sys/sys/pioctl.h 217747 2011-01-23 12:44:17Z kib $
 */

#ifndef _SYS_PIOCTL_H
# define _SYS_PIOCTL_H

# include <sys/ioccom.h>

struct procfs_status {
	int	state;	/* Running, stopped, something else? */
	int	flags;	/* Any flags */
	unsigned long	events;	/* Events to stop on */
	int	why;	/* What event, if any, proc stopped on */
	unsigned long	val;	/* Any extra data */
};

# define	PIOCBIS	_IOWINT('p', 1)	/* Set event flag */
# define	PIOCBIC	_IOWINT('p', 2)	/* Clear event flag */
# define	PIOCSFL	_IOWINT('p', 3)	/* Set flags */
			/* wait for proc to stop */
# define	PIOCWAIT	_IOR('p', 4, struct procfs_status)
# define	PIOCCONT	_IOWINT('p', 5)	/* Continue a process */
			/* Get proc status */
# define	PIOCSTATUS	_IOR('p', 6, struct procfs_status)
# define	PIOCGFL	_IOR('p', 7, unsigned int)	/* Get flags */

# define	S_EXEC	0x00000001	/* stop-on-exec */
# define	S_SIG	0x00000002	/* stop-on-signal */
# define	S_SCE	0x00000004	/* stop on syscall entry */
# define	S_SCX	0x00000008	/* stop on syscall exit */
# define	S_CORE	0x00000010	/* stop on coredump */
# define	S_EXIT	0x00000020	/* stop on exit */
# define	S_ALLSTOPS  0x003f	/* stop on all events */

/*
 * If PF_LINGER is set in procp->p_pfsflags, then the last close
 * of a /proc/<pid>/mem file will not clear out the stops and continue
 * the process.
 */

# define PF_LINGER	0x01	/* Keep stops around after last close */
# define PF_ISUGID	0x02	/* Ignore UID/GID changes */
# define PF_FORK	0x04	/* Retain settings on fork() */
#endif


code:
/*-
 * Copyright (c) 1996 John S. Dyson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice immediately at the beginning of the file, without modification,
 *    this list of conditions, and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Absolutely no warranty of function or purpose is made by the author
 *    John S. Dyson.
 * 4. This work was done expressly for inclusion into FreeBSD.  Other use
 *    is allowed if this notation is included.
 * 5. Modifications may be freely made to this file if the above conditions
 *    are met.
 *
 * $FreeBSD: release/9.0.0/sys/sys/pipe.h 226578 2011-10-20 18:54:05Z kib $
 */

#ifndef _SYS_PIPE_H_
#define _SYS_PIPE_H_

#ifndef _KERNEL
#error "no user-servicable parts inside"
#endif

/*
 * Pipe buffer size, keep moderate in value, pipes take kva space.
 */
#ifndef PIPE_SIZE
#define PIPE_SIZE	16384
#endif

#ifndef BIG_PIPE_SIZE
#define BIG_PIPE_SIZE	(64*1024)
#endif

#ifndef SMALL_PIPE_SIZE
#define SMALL_PIPE_SIZE	PAGE_SIZE
#endif

/*
 * PIPE_MINDIRECT MUST be smaller than PIPE_SIZE and MUST be bigger
 * than PIPE_BUF.
 */
#ifndef PIPE_MINDIRECT
#define PIPE_MINDIRECT	8192
#endif

#define PIPENPAGES	(BIG_PIPE_SIZE / PAGE_SIZE + 1)

/*
 * See sys_pipe.c for info on what these limits mean.
 */
extern long	maxpipekva;

/*
 * Pipe buffer information.
 * Separate in, out, cnt are used to simplify calculations.
 * Buffered write is active when the buffer.cnt field is set.
 */
struct pipebuf {
	u_int	cnt;		/* number of chars currently in buffer */
	u_int	in;		/* in pointer */
	u_int	out;		/* out pointer */
	u_int	size;		/* size of buffer */
	caddr_t	buffer;		/* kva of buffer */
};

/*
 * Information to support direct transfers between processes for pipes.
 */
struct pipemapping {
	vm_size_t	cnt;		/* number of chars in buffer */
	vm_size_t	pos;		/* current position of transfer */
	int		npages;		/* number of pages */
	vm_page_t	ms[PIPENPAGES];	/* pages in source process */
};

/*
 * Bits in pipe_state.
 */
#define PIPE_ASYNC	0x004	/* Async? I/O. */
#define PIPE_WANTR	0x008	/* Reader wants some characters. */
#define PIPE_WANTW	0x010	/* Writer wants space to put characters. */
#define PIPE_WANT	0x020	/* Pipe is wanted to be run-down. */
#define PIPE_SEL	0x040	/* Pipe has a select active. */
#define PIPE_EOF	0x080	/* Pipe is in EOF condition. */
#define PIPE_LOCKFL	0x100	/* Process has exclusive access to pointers/data. */
#define PIPE_LWANT	0x200	/* Process wants exclusive access to pointers/data. */
#define PIPE_DIRECTW	0x400	/* Pipe direct write active. */
#define PIPE_DIRECTOK	0x800	/* Direct mode ok. */

/*
 * Per-pipe data structure.
 * Two of these are linked together to produce bi-directional pipes.
 */
struct pipe {
	struct	pipebuf pipe_buffer;	/* data storage */
	struct	pipemapping pipe_map;	/* pipe mapping for direct I/O */
	struct	selinfo pipe_sel;	/* for compat with select */
	struct	timespec pipe_atime;	/* time of last access */
	struct	timespec pipe_mtime;	/* time of last modify */
	struct	timespec pipe_ctime;	/* time of status change */
	struct	sigio *pipe_sigio;	/* information for async I/O */
	struct	pipe *pipe_peer;	/* link with other direction */
	struct	pipepair *pipe_pair;	/* container structure pointer */
	u_int	pipe_state;		/* pipe status info */
	int	pipe_busy;		/* busy flag, mostly to handle rundown sanely */
	int	pipe_present;		/* still present? */
	ino_t	pipe_ino;		/* fake inode for stat(2) */
};

/*
 * Values for the pipe_present.
 */
#define PIPE_ACTIVE		1
#define	PIPE_CLOSING		2
#define	PIPE_FINALIZED		3

/*
 * Container structure to hold the two pipe endpoints, mutex, and label
 * pointer.
 */
struct pipepair {
	struct pipe	pp_rpipe;
	struct pipe	pp_wpipe;
	struct mtx	pp_mtx;
	struct label	*pp_label;
};

#define PIPE_MTX(pipe)		(&(pipe)->pipe_pair->pp_mtx)
#define PIPE_LOCK(pipe)		mtx_lock(PIPE_MTX(pipe))
#define PIPE_UNLOCK(pipe)	mtx_unlock(PIPE_MTX(pipe))
#define PIPE_LOCK_ASSERT(pipe, type)  mtx_assert(PIPE_MTX(pipe), (type))

#endif /* !_SYS_PIPE_H_ */


code:
/*-
 * Copyright (c) 2003-2008, Joseph Koshy
 * Copyright (c) 2007 The FreeBSD Foundation
 * All rights reserved.
 *
 * Portions of this software were developed by A. Joseph Koshy under
 * sponsorship from the FreeBSD Foundation and Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/pmc.h 209196 2010-06-15 09:12:31Z fabient $
 */

#ifndef _SYS_PMC_H_
#define	_SYS_PMC_H_

#include <dev/hwpmc/pmc_events.h>

#include <machine/pmc_mdep.h>
#include <machine/profile.h>

#define	PMC_MODULE_NAME		"hwpmc"
#define	PMC_NAME_MAX		16 /* HW counter name size */
#define	PMC_CLASS_MAX		6  /* max #classes of PMCs per-system */

/*
 * Kernel<->userland API version number [MMmmpppp]
 *
 * Major numbers are to be incremented when an incompatible change to
 * the ABI occurs that older clients will not be able to handle.
 *
 * Minor numbers are incremented when a backwards compatible change
 * occurs that allows older correct programs to run unchanged.  For
 * example, when support for a new PMC type is added.
 *
 * The patch version is incremented for every bug fix.
 */
#define	PMC_VERSION_MAJOR	0x03
#define	PMC_VERSION_MINOR	0x01
#define	PMC_VERSION_PATCH	0x0000

#define	PMC_VERSION		(PMC_VERSION_MAJOR << 24 |		\
	PMC_VERSION_MINOR << 16 | PMC_VERSION_PATCH)

/*
 * Kinds of CPUs known.
 *
 * We keep track of CPU variants that need to be distinguished in
 * some way for PMC operations.  CPU names are grouped by manufacturer
 * and numbered sparsely in order to minimize changes to the ABI involved
 * when new CPUs are added.
 */

#define	__PMC_CPUS()						\
	__PMC_CPU(AMD_K7,	0x00,	"AMD K7")		\
	__PMC_CPU(AMD_K8,	0x01,	"AMD K8")		\
	__PMC_CPU(INTEL_P5,	0x80,	"Intel Pentium")	\
	__PMC_CPU(INTEL_P6,	0x81,	"Intel Pentium Pro")	\
	__PMC_CPU(INTEL_CL,	0x82,	"Intel Celeron")	\
	__PMC_CPU(INTEL_PII,	0x83,	"Intel Pentium II")	\
	__PMC_CPU(INTEL_PIII,	0x84,	"Intel Pentium III")	\
	__PMC_CPU(INTEL_PM,	0x85,	"Intel Pentium M")	\
	__PMC_CPU(INTEL_PIV,	0x86,	"Intel Pentium IV")	\
	__PMC_CPU(INTEL_CORE,	0x87,	"Intel Core Solo/Duo")	\
	__PMC_CPU(INTEL_CORE2,	0x88,	"Intel Core2")		\
	__PMC_CPU(INTEL_CORE2EXTREME,	0x89,	"Intel Core2 Extreme")	\
	__PMC_CPU(INTEL_ATOM,	0x8A,	"Intel Atom") \
	__PMC_CPU(INTEL_COREI7, 0x8B,   "Intel Core i7") \
	__PMC_CPU(INTEL_WESTMERE, 0x8C,   "Intel Westmere") \
	__PMC_CPU(INTEL_XSCALE,	0x100,	"Intel XScale") \
	__PMC_CPU(MIPS_24K,     0x200,  "MIPS 24K")

enum pmc_cputype {
#undef	__PMC_CPU
#define	__PMC_CPU(S,V,D)	PMC_CPU_##S = V,
	__PMC_CPUS()
};

#define	PMC_CPU_FIRST	PMC_CPU_AMD_K7
#define	PMC_CPU_LAST	PMC_CPU_MIPS_24K

/*
 * Classes of PMCs
 */

#define	__PMC_CLASSES()							\
	__PMC_CLASS(TSC)	/* CPU Timestamp counter */		\
	__PMC_CLASS(K7)		/* AMD K7 performance counters */	\
	__PMC_CLASS(K8)		/* AMD K8 performance counters */	\
	__PMC_CLASS(P5)		/* Intel Pentium counters */		\
	__PMC_CLASS(P6)		/* Intel Pentium Pro counters */	\
	__PMC_CLASS(P4)		/* Intel Pentium-IV counters */		\
	__PMC_CLASS(IAF)	/* Intel Core2/Atom, fixed function */	\
	__PMC_CLASS(IAP)	/* Intel Core...Atom, programmable */	\
	__PMC_CLASS(UCF)	/* Intel Uncore fixed function */	\
	__PMC_CLASS(UCP)	/* Intel Uncore programmable */		\
	__PMC_CLASS(XSCALE)	/* Intel XScale counters */		\
	__PMC_CLASS(MIPS24K)    /* MIPS 24K */

enum pmc_class {
#undef  __PMC_CLASS
#define	__PMC_CLASS(N)	PMC_CLASS_##N ,
	__PMC_CLASSES()
};

#define	PMC_CLASS_FIRST	PMC_CLASS_TSC
#define	PMC_CLASS_LAST	PMC_CLASS_MIPS24K

/*
 * A PMC can be in the following states:
 *
 * Hardware states:
 *   DISABLED   -- administratively prohibited from being used.
 *   FREE       -- HW available for use
 * Software states:
 *   ALLOCATED  -- allocated
 *   STOPPED    -- allocated, but not counting events
 *   RUNNING    -- allocated, and in operation; 'pm_runcount'
 *                 holds the number of CPUs using this PMC at
 *                 a given instant
 *   DELETED    -- being destroyed
 */

#define	__PMC_HWSTATES()			\
	__PMC_STATE(DISABLED)			\
	__PMC_STATE(FREE)

#define	__PMC_SWSTATES()			\
	__PMC_STATE(ALLOCATED)			\
	__PMC_STATE(STOPPED)			\
	__PMC_STATE(RUNNING)			\
	__PMC_STATE(DELETED)

#define	__PMC_STATES()				\
	__PMC_HWSTATES()			\
	__PMC_SWSTATES()

enum pmc_state {
#undef	__PMC_STATE
#define	__PMC_STATE(S)	PMC_STATE_##S,
	__PMC_STATES()
	__PMC_STATE(MAX)
};

#define	PMC_STATE_FIRST	PMC_STATE_DISABLED
#define	PMC_STATE_LAST	PMC_STATE_DELETED

/*
 * An allocated PMC may used as a 'global' counter or as a
 * 'thread-private' one.  Each such mode of use can be in either
 * statistical sampling mode or in counting mode.  Thus a PMC in use
 *
 * SS i.e., SYSTEM STATISTICAL  -- system-wide statistical profiling
 * SC i.e., SYSTEM COUNTER      -- system-wide counting mode
 * TS i.e., THREAD STATISTICAL  -- thread virtual, statistical profiling
 * TC i.e., THREAD COUNTER      -- thread virtual, counting mode
 *
 * Statistical profiling modes rely on the PMC periodically delivering
 * a interrupt to the CPU (when the configured number of events have
 * been measured), so the PMC must have the ability to generate
 * interrupts.
 *
 * In counting modes, the PMC counts its configured events, with the
 * value of the PMC being read whenever needed by its owner process.
 *
 * The thread specific modes "virtualize" the PMCs -- the PMCs appear
 * to be thread private and count events only when the profiled thread
 * actually executes on the CPU.
 *
 * The system-wide "global" modes keep the PMCs running all the time
 * and are used to measure the behaviour of the whole system.
 */

#define	__PMC_MODES()				\
	__PMC_MODE(SS,	0)			\
	__PMC_MODE(SC,	1)			\
	__PMC_MODE(TS,	2)			\
	__PMC_MODE(TC,	3)

enum pmc_mode {
#undef	__PMC_MODE
#define	__PMC_MODE(M,N)	PMC_MODE_##M = N,
	__PMC_MODES()
};

#define	PMC_MODE_FIRST	PMC_MODE_SS
#define	PMC_MODE_LAST	PMC_MODE_TC

#define	PMC_IS_COUNTING_MODE(mode)				\
	((mode) == PMC_MODE_SC || (mode) == PMC_MODE_TC)
#define	PMC_IS_SYSTEM_MODE(mode)				\
	((mode) == PMC_MODE_SS || (mode) == PMC_MODE_SC)
#define	PMC_IS_SAMPLING_MODE(mode)				\
	((mode) == PMC_MODE_SS || (mode) == PMC_MODE_TS)
#define	PMC_IS_VIRTUAL_MODE(mode)				\
	((mode) == PMC_MODE_TS || (mode) == PMC_MODE_TC)

/*
 * PMC row disposition
 */

#define	__PMC_DISPOSITIONS(N)					\
	__PMC_DISP(STANDALONE)	/* global/disabled counters */	\
	__PMC_DISP(FREE)	/* free/available */		\
	__PMC_DISP(THREAD)	/* thread-virtual PMCs */	\
	__PMC_DISP(UNKNOWN)	/* sentinel */

enum pmc_disp {
#undef	__PMC_DISP
#define	__PMC_DISP(D)	PMC_DISP_##D ,
	__PMC_DISPOSITIONS()
};

#define	PMC_DISP_FIRST	PMC_DISP_STANDALONE
#define	PMC_DISP_LAST	PMC_DISP_THREAD

/*
 * Counter capabilities
 *
 * __PMC_CAPS(NAME, VALUE, DESCRIPTION)
 */

#define	__PMC_CAPS()							\
	__PMC_CAP(INTERRUPT,	0, "generate interrupts")		\
	__PMC_CAP(USER,		1, "count user-mode events")		\
	__PMC_CAP(SYSTEM,	2, "count system-mode events")		\
	__PMC_CAP(EDGE,		3, "do edge detection of events")	\
	__PMC_CAP(THRESHOLD,	4, "ignore events below a threshold")	\
	__PMC_CAP(READ,		5, "read PMC counter")			\
	__PMC_CAP(WRITE,	6, "reprogram PMC counter")		\
	__PMC_CAP(INVERT,	7, "invert comparision sense")		\
	__PMC_CAP(QUALIFIER,	8, "further qualify monitored events")	\
	__PMC_CAP(PRECISE,	9, "perform precise sampling")		\
	__PMC_CAP(TAGGING,	10, "tag upstream events")		\
	__PMC_CAP(CASCADE,	11, "cascade counters")

enum pmc_caps
{
#undef	__PMC_CAP
#define	__PMC_CAP(NAME, VALUE, DESCR)	PMC_CAP_##NAME = (1 << VALUE) ,
	__PMC_CAPS()
};

#define	PMC_CAP_FIRST		PMC_CAP_INTERRUPT
#define	PMC_CAP_LAST		PMC_CAP_CASCADE

/*
 * PMC Event Numbers
 *
 * These are generated from the definitions in "dev/hwpmc/pmc_events.h".
 */

enum pmc_event {
#undef	__PMC_EV
#undef	__PMC_EV_BLOCK
#define	__PMC_EV_BLOCK(C,V)	PMC_EV_ ## C ## __BLOCK_START = (V) - 1 ,
#define	__PMC_EV(C,N)		PMC_EV_ ## C ## _ ## N ,
	__PMC_EVENTS()
};

/*
 * PMC SYSCALL INTERFACE
 */

/*
 * "PMC_OPS" -- these are the commands recognized by the kernel
 * module, and are used when performing a system call from userland.
 */
#define	__PMC_OPS()							\
	__PMC_OP(CONFIGURELOG, "Set log file")				\
	__PMC_OP(FLUSHLOG, "Flush log file")				\
	__PMC_OP(GETCPUINFO, "Get system CPU information")		\
	__PMC_OP(GETDRIVERSTATS, "Get driver statistics")		\
	__PMC_OP(GETMODULEVERSION, "Get module version")		\
	__PMC_OP(GETPMCINFO, "Get per-cpu PMC information")		\
	__PMC_OP(PMCADMIN, "Set PMC state")				\
	__PMC_OP(PMCALLOCATE, "Allocate and configure a PMC")		\
	__PMC_OP(PMCATTACH, "Attach a PMC to a process")		\
	__PMC_OP(PMCDETACH, "Detach a PMC from a process")		\
	__PMC_OP(PMCGETMSR, "Get a PMC's hardware address")		\
	__PMC_OP(PMCRELEASE, "Release a PMC")				\
	__PMC_OP(PMCRW, "Read/Set a PMC")				\
	__PMC_OP(PMCSETCOUNT, "Set initial count/sampling rate")	\
	__PMC_OP(PMCSTART, "Start a PMC")				\
	__PMC_OP(PMCSTOP, "Stop a PMC")					\
	__PMC_OP(WRITELOG, "Write a cookie to the log file")

enum pmc_ops {
#undef	__PMC_OP
#define	__PMC_OP(N, D)	PMC_OP_##N,
	__PMC_OPS()
};

/*
 * Flags used in operations on PMCs.
 */

#define	PMC_F_FORCE		0x00000001 /*OP ADMIN force operation */
#define	PMC_F_DESCENDANTS	0x00000002 /*OP ALLOCATE track descendants */
#define	PMC_F_LOG_PROCCSW	0x00000004 /*OP ALLOCATE track ctx switches */
#define	PMC_F_LOG_PROCEXIT	0x00000008 /*OP ALLOCATE log proc exits */
#define	PMC_F_NEWVALUE		0x00000010 /*OP RW write new value */
#define	PMC_F_OLDVALUE		0x00000020 /*OP RW get old value */
#define	PMC_F_KGMON		0x00000040 /*OP ALLOCATE kgmon(8) profiling */
/* V2 API */
#define	PMC_F_CALLCHAIN		0x00000080 /*OP ALLOCATE capture callchains */

/* internal flags */
#define	PMC_F_ATTACHED_TO_OWNER	0x00010000 /*attached to owner*/
#define	PMC_F_NEEDS_LOGFILE	0x00020000 /*needs log file */
#define	PMC_F_ATTACH_DONE	0x00040000 /*attached at least once */

#define	PMC_CALLCHAIN_DEPTH_MAX	32
#define	PMC_CC_F_USERSPACE	0x01	   /*userspace callchain*/

/*
 * Cookies used to denote allocated PMCs, and the values of PMCs.
 */

typedef uint32_t	pmc_id_t;
typedef uint64_t	pmc_value_t;

#define	PMC_ID_INVALID		(~ (pmc_id_t) 0)

/*
 * PMC IDs have the following format:
 *
 * +--------+----------+-----------+-----------+
 * |   CPU  | PMC MODE | PMC CLASS | ROW INDEX |
 * +--------+----------+-----------+-----------+
 *
 * where each field is 8 bits wide.  Field 'CPU' is set to the
 * requested CPU for system-wide PMCs or PMC_CPU_ANY for process-mode
 * PMCs.  Field 'PMC MODE' is the allocated PMC mode.  Field 'PMC
 * CLASS' is the class of the PMC.  Field 'ROW INDEX' is the row index
 * for the PMC.
 *
 * The 'ROW INDEX' ranges over 0..NWPMCS where NHWPMCS is the total
 * number of hardware PMCs on this cpu.
 */

#define	PMC_ID_TO_ROWINDEX(ID)	((ID) & 0xFF)
#define	PMC_ID_TO_CLASS(ID)	(((ID) & 0xFF00) >> 8)
#define	PMC_ID_TO_MODE(ID)	(((ID) & 0xFF0000) >> 16)
#define	PMC_ID_TO_CPU(ID)	(((ID) & 0xFF000000) >> 24)
#define	PMC_ID_MAKE_ID(CPU,MODE,CLASS,ROWINDEX)			\
	((((CPU) & 0xFF) << 24) | (((MODE) & 0xFF) << 16) |	\
	(((CLASS) & 0xFF) << 8) | ((ROWINDEX) & 0xFF))

/*
 * Data structures for system calls supported by the pmc driver.
 */

/*
 * OP PMCALLOCATE
 *
 * Allocate a PMC on the named CPU.
 */

#define	PMC_CPU_ANY	~0

struct pmc_op_pmcallocate {
	uint32_t	pm_caps;	/* PMC_CAP_* */
	uint32_t	pm_cpu;		/* CPU number or PMC_CPU_ANY */
	enum pmc_class	pm_class;	/* class of PMC desired */
	enum pmc_event	pm_ev;		/* [enum pmc_event] desired */
	uint32_t	pm_flags;	/* additional modifiers PMC_F_* */
	enum pmc_mode	pm_mode;	/* desired mode */
	pmc_id_t	pm_pmcid;	/* [return] process pmc id */

	union pmc_md_op_pmcallocate pm_md; /* MD layer extensions */
};

/*
 * OP PMCADMIN
 *
 * Set the administrative state (i.e., whether enabled or disabled) of
 * a PMC 'pm_pmc' on CPU 'pm_cpu'.  Note that 'pm_pmc' specifies an
 * absolute PMC number and need not have been first allocated by the
 * calling process.
 */

struct pmc_op_pmcadmin {
	int		pm_cpu;		/* CPU# */
	uint32_t	pm_flags;	/* flags */
	int		pm_pmc;         /* PMC# */
	enum pmc_state  pm_state;	/* desired state */
};

/*
 * OP PMCATTACH / OP PMCDETACH
 *
 * Attach/detach a PMC and a process.
 */

struct pmc_op_pmcattach {
	pmc_id_t	pm_pmc;		/* PMC to attach to */
	pid_t		pm_pid;		/* target process */
};

/*
 * OP PMCSETCOUNT
 *
 * Set the sampling rate (i.e., the reload count) for statistical counters.
 * 'pm_pmcid' need to have been previously allocated using PMCALLOCATE.
 */

struct pmc_op_pmcsetcount {
	pmc_value_t	pm_count;	/* initial/sample count */
	pmc_id_t	pm_pmcid;	/* PMC id to set */
};

/*
 * OP PMCRW
 *
 * Read the value of a PMC named by 'pm_pmcid'.  'pm_pmcid' needs
 * to have been previously allocated using PMCALLOCATE.
 */

struct pmc_op_pmcrw {
	uint32_t	pm_flags;	/* PMC_F_{OLD,NEW}VALUE*/
	pmc_id_t	pm_pmcid;	/* pmc id */
	pmc_value_t	pm_value;	/* new&returned value */
};

/*
 * OP GETPMCINFO
 *
 * retrieve PMC state for a named CPU.  The caller is expected to
 * allocate 'npmc' * 'struct pmc_info' bytes of space for the return
 * values.
 */

struct pmc_info {
	char		pm_name[PMC_NAME_MAX]; /* pmc name */
	enum pmc_class	pm_class;	/* enum pmc_class */
	int		pm_enabled;	/* whether enabled */
	enum pmc_disp	pm_rowdisp;	/* FREE, THREAD or STANDLONE */
	pid_t		pm_ownerpid;	/* owner, or -1 */
	enum pmc_mode	pm_mode;	/* current mode [enum pmc_mode] */
	enum pmc_event	pm_event;	/* current event */
	uint32_t	pm_flags;	/* current flags */
	pmc_value_t	pm_reloadcount;	/* sampling counters only */
};

struct pmc_op_getpmcinfo {
	int32_t		pm_cpu;		/* 0 <= cpu < mp_maxid */
	struct pmc_info	pm_pmcs[];	/* space for 'npmc' structures */
};

/*
 * OP GETCPUINFO
 *
 * Retrieve system CPU information.
 */

struct pmc_classinfo {
	enum pmc_class	pm_class;	/* class id */
	uint32_t	pm_caps;	/* counter capabilities */
	uint32_t	pm_width;	/* width of the PMC */
	uint32_t	pm_num;		/* number of PMCs in class */
};

struct pmc_op_getcpuinfo {
	enum pmc_cputype pm_cputype; /* what kind of CPU */
	uint32_t	pm_ncpu;    /* max CPU number */
	uint32_t	pm_npmc;    /* #PMCs per CPU */
	uint32_t	pm_nclass;  /* #classes of PMCs */
	struct pmc_classinfo  pm_classes[PMC_CLASS_MAX];
};

/*
 * OP CONFIGURELOG
 *
 * Configure a log file for writing system-wide statistics to.
 */

struct pmc_op_configurelog {
	int		pm_flags;
	int		pm_logfd;   /* logfile fd (or -1) */
};

/*
 * OP GETDRIVERSTATS
 *
 * Retrieve pmc(4) driver-wide statistics.
 */

struct pmc_op_getdriverstats {
	int	pm_intr_ignored;	/* #interrupts ignored */
	int	pm_intr_processed;	/* #interrupts processed */
	int	pm_intr_bufferfull;	/* #interrupts with ENOSPC */
	int	pm_syscalls;		/* #syscalls */
	int	pm_syscall_errors;	/* #syscalls with errors */
	int	pm_buffer_requests;	/* #buffer requests */
	int	pm_buffer_requests_failed; /* #failed buffer requests */
	int	pm_log_sweeps;		/* #sample buffer processing passes */
};

/*
 * OP RELEASE / OP START / OP STOP
 *
 * Simple operations on a PMC id.
 */

struct pmc_op_simple {
	pmc_id_t	pm_pmcid;
};

/*
 * OP WRITELOG
 *
 * Flush the current log buffer and write 4 bytes of user data to it.
 */

struct pmc_op_writelog {
	uint32_t	pm_userdata;
};

/*
 * OP GETMSR
 *
 * Retrieve the machine specific address assoicated with the allocated
 * PMC.  This number can be used subsequently with a read-performance-counter
 * instruction.
 */

struct pmc_op_getmsr {
	uint32_t	pm_msr;		/* machine specific address */
	pmc_id_t	pm_pmcid;	/* allocated pmc id */
};

#ifdef _KERNEL

#include <sys/malloc.h>
#include <sys/sysctl.h>

#include <machine/frame.h>

#define	PMC_HASH_SIZE				16
#define	PMC_MTXPOOL_SIZE			32
#define	PMC_LOG_BUFFER_SIZE			4
#define	PMC_NLOGBUFFERS				16
#define	PMC_NSAMPLES				32
#define	PMC_CALLCHAIN_DEPTH			8

#define PMC_SYSCTL_NAME_PREFIX "kern." PMC_MODULE_NAME "."

/*
 * Locking keys
 *
 * (b) - pmc_bufferlist_mtx (spin lock)
 * (k) - pmc_kthread_mtx (sleep lock)
 * (o) - po->po_mtx (spin lock)
 */

/*
 * PMC commands
 */

struct pmc_syscall_args {
	uint32_t	pmop_code;	/* one of PMC_OP_* */
	void		*pmop_data;	/* syscall parameter */
};

/*
 * Interface to processor specific s1tuff
 */

/*
 * struct pmc_descr
 *
 * Machine independent (i.e., the common parts) of a human readable
 * PMC description.
 */

struct pmc_descr {
	char		pd_name[PMC_NAME_MAX]; /* name */
	uint32_t	pd_caps;	/* capabilities */
	enum pmc_class	pd_class;	/* class of the PMC */
	uint32_t	pd_width;	/* width in bits */
};

/*
 * struct pmc_target
 *
 * This structure records all the target processes associated with a
 * PMC.
 */

struct pmc_target {
	LIST_ENTRY(pmc_target)	pt_next;
	struct pmc_process	*pt_process; /* target descriptor */
};

/*
 * struct pmc
 *
 * Describes each allocated PMC.
 *
 * Each PMC has precisely one owner, namely the process that allocated
 * the PMC.
 *
 * A PMC may be attached to multiple target processes.  The
 * 'pm_targets' field links all the target processes being monitored
 * by this PMC.
 *
 * The 'pm_savedvalue' field is protected by a mutex.
 *
 * On a multi-cpu machine, multiple target threads associated with a
 * process-virtual PMC could be concurrently executing on different
 * CPUs.  The 'pm_runcount' field is atomically incremented every time
 * the PMC gets scheduled on a CPU and atomically decremented when it
 * get descheduled.  Deletion of a PMC is only permitted when this
 * field is '0'.
 *
 */

struct pmc {
	LIST_HEAD(,pmc_target)	pm_targets;	/* list of target processes */
	LIST_ENTRY(pmc)		pm_next;	/* owner's list */

	/*
	 * System-wide PMCs are allocated on a CPU and are not moved
	 * around.  For system-wide PMCs we record the CPU the PMC was
	 * allocated on in the 'CPU' field of the pmc ID.
	 *
	 * Virtual PMCs run on whichever CPU is currently executing
	 * their targets' threads.  For these PMCs we need to save
	 * their current PMC counter values when they are taken off
	 * CPU.
	 */

	union {
		pmc_value_t	pm_savedvalue;	/* Virtual PMCS */
	} pm_gv;

	/*
	 * For sampling mode PMCs, we keep track of the PMC's "reload
	 * count", which is the counter value to be loaded in when
	 * arming the PMC for the next counting session.  For counting
	 * modes on PMCs that are read-only (e.g., the x86 TSC), we
	 * keep track of the initial value at the start of
	 * counting-mode operation.
	 */

	union {
		pmc_value_t	pm_reloadcount;	/* sampling PMC modes */
		pmc_value_t	pm_initial;	/* counting PMC modes */
	} pm_sc;

	uint32_t	pm_stalled;	/* marks stalled sampling PMCs */
	uint32_t	pm_caps;	/* PMC capabilities */
	enum pmc_event	pm_event;	/* event being measured */
	uint32_t	pm_flags;	/* additional flags PMC_F_... */
	struct pmc_owner *pm_owner;	/* owner thread state */
	int		pm_runcount;	/* #cpus currently on */
	enum pmc_state	pm_state;	/* current PMC state */

	/*
	 * The PMC ID field encodes the row-index for the PMC, its
	 * mode, class and the CPU# associated with the PMC.
	 */

	pmc_id_t	pm_id;		/* allocated PMC id */

	/* md extensions */
	union pmc_md_pmc	pm_md;
};

/*
 * Accessor macros for 'struct pmc'
 */

#define	PMC_TO_MODE(P)		PMC_ID_TO_MODE((P)->pm_id)
#define	PMC_TO_CLASS(P)		PMC_ID_TO_CLASS((P)->pm_id)
#define	PMC_TO_ROWINDEX(P)	PMC_ID_TO_ROWINDEX((P)->pm_id)
#define	PMC_TO_CPU(P)		PMC_ID_TO_CPU((P)->pm_id)

/*
 * struct pmc_process
 *
 * Record a 'target' process being profiled.
 *
 * The target process being profiled could be different from the owner
 * process which allocated the PMCs.  Each target process descriptor
 * is associated with NHWPMC 'struct pmc *' pointers.  Each PMC at a
 * given hardware row-index 'n' will use slot 'n' of the 'pp_pmcs[]'
 * array.  The size of this structure is thus PMC architecture
 * dependent.
 *
 */

struct pmc_targetstate {
	struct pmc	*pp_pmc;   /* target PMC */
	pmc_value_t	pp_pmcval; /* per-process value */
};

struct pmc_process {
	LIST_ENTRY(pmc_process) pp_next;	/* hash chain */
	int		pp_refcnt;		/* reference count */
	uint32_t	pp_flags;		/* flags PMC_PP_* */
	struct proc	*pp_proc;		/* target thread */
	struct pmc_targetstate pp_pmcs[];       /* NHWPMCs */
};

#define	PMC_PP_ENABLE_MSR_ACCESS	0x00000001

/*
 * struct pmc_owner
 *
 * We associate a PMC with an 'owner' process.
 *
 * A process can be associated with 0..NCPUS*NHWPMC PMCs during its
 * lifetime, where NCPUS is the numbers of CPUS in the system and
 * NHWPMC is the number of hardware PMCs per CPU.  These are
 * maintained in the list headed by the 'po_pmcs' to save on space.
 *
 */

struct pmc_owner  {
	LIST_ENTRY(pmc_owner)	po_next;	/* hash chain */
	LIST_ENTRY(pmc_owner)	po_ssnext;	/* list of SS PMC owners */
	LIST_HEAD(, pmc)	po_pmcs;	/* owned PMC list */
	TAILQ_HEAD(, pmclog_buffer) po_logbuffers; /* (o) logbuffer list */
	struct mtx		po_mtx;		/* spin lock for (o) */
	struct proc		*po_owner;	/* owner proc */
	uint32_t		po_flags;	/* (k) flags PMC_PO_* */
	struct proc		*po_kthread;	/* (k) helper kthread */
	struct pmclog_buffer	*po_curbuf;	/* current log buffer */
	struct file		*po_file;	/* file reference */
	int			po_error;	/* recorded error */
	short			po_sscount;	/* # SS PMCs owned */
	short			po_logprocmaps;	/* global mappings done */
};

#define	PMC_PO_OWNS_LOGFILE		0x00000001 /* has a log file */
#define	PMC_PO_SHUTDOWN			0x00000010 /* in the process of shutdown */
#define	PMC_PO_INITIAL_MAPPINGS_DONE	0x00000020

/*
 * struct pmc_hw -- describe the state of the PMC hardware
 *
 * When in use, a HW PMC is associated with one allocated 'struct pmc'
 * pointed to by field 'phw_pmc'.  When inactive, this field is NULL.
 *
 * On an SMP box, one or more HW PMC's in process virtual mode with
 * the same 'phw_pmc' could be executing on different CPUs.  In order
 * to handle this case correctly, we need to ensure that only
 * incremental counts get added to the saved value in the associated
 * 'struct pmc'.  The 'phw_save' field is used to keep the saved PMC
 * value at the time the hardware is started during this context
 * switch (i.e., the difference between the new (hardware) count and
 * the saved count is atomically added to the count field in 'struct
 * pmc' at context switch time).
 *
 */

struct pmc_hw {
	uint32_t	phw_state;	/* see PHW_* macros below */
	struct pmc	*phw_pmc;	/* current thread PMC */
};

#define	PMC_PHW_RI_MASK		0x000000FF
#define	PMC_PHW_CPU_SHIFT	8
#define	PMC_PHW_CPU_MASK	0x0000FF00
#define	PMC_PHW_FLAGS_SHIFT	16
#define	PMC_PHW_FLAGS_MASK	0xFFFF0000

#define	PMC_PHW_INDEX_TO_STATE(ri)	((ri) & PMC_PHW_RI_MASK)
#define	PMC_PHW_STATE_TO_INDEX(state)	((state) & PMC_PHW_RI_MASK)
#define	PMC_PHW_CPU_TO_STATE(cpu)	(((cpu) << PMC_PHW_CPU_SHIFT) & \
	PMC_PHW_CPU_MASK)
#define	PMC_PHW_STATE_TO_CPU(state)	(((state) & PMC_PHW_CPU_MASK) >> \
	PMC_PHW_CPU_SHIFT)
#define	PMC_PHW_FLAGS_TO_STATE(flags)	(((flags) << PMC_PHW_FLAGS_SHIFT) & \
	PMC_PHW_FLAGS_MASK)
#define	PMC_PHW_STATE_TO_FLAGS(state)	(((state) & PMC_PHW_FLAGS_MASK) >> \
	PMC_PHW_FLAGS_SHIFT)
#define	PMC_PHW_FLAG_IS_ENABLED		(PMC_PHW_FLAGS_TO_STATE(0x01))
#define	PMC_PHW_FLAG_IS_SHAREABLE	(PMC_PHW_FLAGS_TO_STATE(0x02))

/*
 * struct pmc_sample
 *
 * Space for N (tunable) PC samples and associated control data.
 */

struct pmc_sample {
	uint16_t		ps_nsamples;	/* callchain depth */
	uint8_t			ps_cpu;		/* cpu number */
	uint8_t			ps_flags;	/* other flags */
	pid_t			ps_pid;		/* process PID or -1 */
	struct thread		*ps_td;		/* which thread */
	struct pmc		*ps_pmc;	/* interrupting PMC */
	uintptr_t		*ps_pc;		/* (const) callchain start */
};

#define	PMC_SAMPLE_FREE		((uint16_t) 0)
#define	PMC_SAMPLE_INUSE	((uint16_t) 0xFFFF)

struct pmc_samplebuffer {
	struct pmc_sample * volatile ps_read;	/* read pointer */
	struct pmc_sample * volatile ps_write;	/* write pointer */
	uintptr_t		*ps_callchains;	/* all saved call chains */
	struct pmc_sample	*ps_fence;	/* one beyond ps_samples[] */
	struct pmc_sample	ps_samples[];	/* array of sample entries */
};

/*
 * struct pmc_cpustate
 *
 * A CPU is modelled as a collection of HW PMCs with space for additional
 * flags.
 */

struct pmc_cpu {
	uint32_t	pc_state;	/* physical cpu number + flags */
	struct pmc_samplebuffer *pc_sb; /* space for samples */
	struct pmc_hw	*pc_hwpmcs[];	/* 'npmc' pointers */
};

#define	PMC_PCPU_CPU_MASK		0x000000FF
#define	PMC_PCPU_FLAGS_MASK		0xFFFFFF00
#define	PMC_PCPU_FLAGS_SHIFT		8
#define	PMC_PCPU_STATE_TO_CPU(S)	((S) & PMC_PCPU_CPU_MASK)
#define	PMC_PCPU_STATE_TO_FLAGS(S)	(((S) & PMC_PCPU_FLAGS_MASK) >> PMC_PCPU_FLAGS_SHIFT)
#define	PMC_PCPU_FLAGS_TO_STATE(F)	(((F) << PMC_PCPU_FLAGS_SHIFT) & PMC_PCPU_FLAGS_MASK)
#define	PMC_PCPU_CPU_TO_STATE(C)	((C) & PMC_PCPU_CPU_MASK)
#define	PMC_PCPU_FLAG_HTT		(PMC_PCPU_FLAGS_TO_STATE(0x1))

/*
 * struct pmc_binding
 *
 * CPU binding information.
 */

struct pmc_binding {
	int	pb_bound;	/* is bound? */
	int	pb_cpu;		/* if so, to which CPU */
};

struct pmc_mdep;

/*
 * struct pmc_classdep
 *
 * PMC class-dependent operations.
 */
struct pmc_classdep {
	uint32_t	pcd_caps;	/* class capabilities */
	enum pmc_class	pcd_class;	/* class id */
	int		pcd_num;	/* number of PMCs */
	int		pcd_ri;		/* row index of the first PMC in class */
	int		pcd_width;	/* width of the PMC */

	/* configuring/reading/writing the hardware PMCs */
	int (*pcd_config_pmc)(int _cpu, int _ri, struct pmc *_pm);
	int (*pcd_get_config)(int _cpu, int _ri, struct pmc **_ppm);
	int (*pcd_read_pmc)(int _cpu, int _ri, pmc_value_t *_value);
	int (*pcd_write_pmc)(int _cpu, int _ri, pmc_value_t _value);

	/* pmc allocation/release */
	int (*pcd_allocate_pmc)(int _cpu, int _ri, struct pmc *_t,
		const struct pmc_op_pmcallocate *_a);
	int (*pcd_release_pmc)(int _cpu, int _ri, struct pmc *_pm);

	/* starting and stopping PMCs */
	int (*pcd_start_pmc)(int _cpu, int _ri);
	int (*pcd_stop_pmc)(int _cpu, int _ri);

	/* description */
	int (*pcd_describe)(int _cpu, int _ri, struct pmc_info *_pi,
		struct pmc **_ppmc);

	/* class-dependent initialization & finalization */
	int (*pcd_pcpu_init)(struct pmc_mdep *_md, int _cpu);
	int (*pcd_pcpu_fini)(struct pmc_mdep *_md, int _cpu);

	/* machine-specific interface */
	int (*pcd_get_msr)(int _ri, uint32_t *_msr);
};

/*
 * struct pmc_mdep
 *
 * Machine dependent bits needed per CPU type.
 */

struct pmc_mdep  {
	uint32_t	pmd_cputype;    /* from enum pmc_cputype */
	uint32_t	pmd_npmc;	/* number of PMCs per CPU */
	uint32_t	pmd_nclass;	/* number of PMC classes present */

	/*
	 * Machine dependent methods.
	 */

	/* per-cpu initialization and finalization */
	int (*pmd_pcpu_init)(struct pmc_mdep *_md, int _cpu);
	int (*pmd_pcpu_fini)(struct pmc_mdep *_md, int _cpu);

	/* thread context switch in/out */
	int (*pmd_switch_in)(struct pmc_cpu *_p, struct pmc_process *_pp);
	int (*pmd_switch_out)(struct pmc_cpu *_p, struct pmc_process *_pp);

	/* handle a PMC interrupt */
	int (*pmd_intr)(int _cpu, struct trapframe *_tf);

	/*
	 * PMC class dependent information.
	 */
	struct pmc_classdep pmd_classdep[];
};

/*
 * Per-CPU state.  This is an array of 'mp_ncpu' pointers
 * to struct pmc_cpu descriptors.
 */

extern struct pmc_cpu **pmc_pcpu;

/* driver statistics */
extern struct pmc_op_getdriverstats pmc_stats;

#if	defined(DEBUG) && DEBUG

/* debug flags, major flag groups */
struct pmc_debugflags {
	int	pdb_CPU;
	int	pdb_CSW;
	int	pdb_LOG;
	int	pdb_MDP;
	int	pdb_MOD;
	int	pdb_OWN;
	int	pdb_PMC;
	int	pdb_PRC;
	int	pdb_SAM;
};

extern struct pmc_debugflags pmc_debugflags;

#define	PMC_DEBUG_STRSIZE		128
#define	PMC_DEBUG_DEFAULT_FLAGS		{ 0, 0, 0, 0, 0, 0, 0, 0 }

#define	PMCDBG(M,N,L,F,...) do {					\
	if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N))	\
		printf(#M ":" #N ":" #L  ": " F "\n", __VA_ARGS__);	\
} while (0)

/* Major numbers */
#define	PMC_DEBUG_MAJ_CPU		0 /* cpu switches */
#define	PMC_DEBUG_MAJ_CSW		1 /* context switches */
#define	PMC_DEBUG_MAJ_LOG		2 /* logging */
#define	PMC_DEBUG_MAJ_MDP		3 /* machine dependent */
#define	PMC_DEBUG_MAJ_MOD		4 /* misc module infrastructure */
#define	PMC_DEBUG_MAJ_OWN		5 /* owner */
#define	PMC_DEBUG_MAJ_PMC		6 /* pmc management */
#define	PMC_DEBUG_MAJ_PRC		7 /* processes */
#define	PMC_DEBUG_MAJ_SAM		8 /* sampling */

/* Minor numbers */

/* Common (8 bits) */
#define	PMC_DEBUG_MIN_ALL		0 /* allocation */
#define	PMC_DEBUG_MIN_REL		1 /* release */
#define	PMC_DEBUG_MIN_OPS		2 /* ops: start, stop, ... */
#define	PMC_DEBUG_MIN_INI		3 /* init */
#define	PMC_DEBUG_MIN_FND		4 /* find */

/* MODULE */
#define	PMC_DEBUG_MIN_PMH	       14 /* pmc_hook */
#define	PMC_DEBUG_MIN_PMS	       15 /* pmc_syscall */

/* OWN */
#define	PMC_DEBUG_MIN_ORM		8 /* owner remove */
#define	PMC_DEBUG_MIN_OMR		9 /* owner maybe remove */

/* PROCESSES */
#define	PMC_DEBUG_MIN_TLK		8 /* link target */
#define	PMC_DEBUG_MIN_TUL		9 /* unlink target */
#define	PMC_DEBUG_MIN_EXT	       10 /* process exit */
#define	PMC_DEBUG_MIN_EXC	       11 /* process exec */
#define	PMC_DEBUG_MIN_FRK	       12 /* process fork */
#define	PMC_DEBUG_MIN_ATT	       13 /* attach/detach */
#define	PMC_DEBUG_MIN_SIG	       14 /* signalling */

/* CONTEXT SWITCHES */
#define	PMC_DEBUG_MIN_SWI		8 /* switch in */
#define	PMC_DEBUG_MIN_SWO		9 /* switch out */

/* PMC */
#define	PMC_DEBUG_MIN_REG		8 /* pmc register */
#define	PMC_DEBUG_MIN_ALR		9 /* allocate row */

/* MACHINE DEPENDENT LAYER */
#define	PMC_DEBUG_MIN_REA		8 /* read */
#define	PMC_DEBUG_MIN_WRI		9 /* write */
#define	PMC_DEBUG_MIN_CFG	       10 /* config */
#define	PMC_DEBUG_MIN_STA	       11 /* start */
#define	PMC_DEBUG_MIN_STO	       12 /* stop */
#define	PMC_DEBUG_MIN_INT	       13 /* interrupts */

/* CPU */
#define	PMC_DEBUG_MIN_BND		8 /* bind */
#define	PMC_DEBUG_MIN_SEL		9 /* select */

/* LOG */
#define	PMC_DEBUG_MIN_GTB		8 /* get buf */
#define	PMC_DEBUG_MIN_SIO		9 /* schedule i/o */
#define	PMC_DEBUG_MIN_FLS	       10 /* flush */
#define	PMC_DEBUG_MIN_SAM	       11 /* sample */

#else
#define	PMCDBG(M,N,L,F,...)		/* nothing */
#endif

/* declare a dedicated memory pool */
MALLOC_DECLARE(M_PMC);

/*
 * Functions
 */

struct pmc_mdep *pmc_md_initialize(void);	/* MD init function */
void	pmc_md_finalize(struct pmc_mdep *_md);	/* MD fini function */
int	pmc_getrowdisp(int _ri);
int	pmc_process_interrupt(int _cpu, struct pmc *_pm,
    struct trapframe *_tf, int _inuserspace);
int	pmc_save_kernel_callchain(uintptr_t *_cc, int _maxsamples,
    struct trapframe *_tf);
int	pmc_save_user_callchain(uintptr_t *_cc, int _maxsamples,
    struct trapframe *_tf);
#endif /* _KERNEL */
#endif /* _SYS_PMC_H_ */


code:
/*-
 * Copyright (c) 2003-2007, Joseph Koshy
 * Copyright (c) 2007 The FreeBSD Foundation
 * All rights reserved.
 *
 * Portions of this software were developed by A. Joseph Koshy under
 * sponsorship from the FreeBSD Foundation and Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/pmckern.h 222813 2011-06-07 08:46:13Z attilio $
 */

/*
 * PMC interface used by the base kernel.
 */

#ifndef _SYS_PMCKERN_H_
#define _SYS_PMCKERN_H_

#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/proc.h>
#include <sys/sx.h>

#define	PMC_FN_PROCESS_EXEC		1
#define	PMC_FN_CSW_IN			2
#define	PMC_FN_CSW_OUT			3
#define	PMC_FN_DO_SAMPLES		4
#define	PMC_FN_KLD_LOAD			5
#define	PMC_FN_KLD_UNLOAD		6
#define	PMC_FN_MMAP			7
#define	PMC_FN_MUNMAP			8
#define	PMC_FN_USER_CALLCHAIN		9

struct pmckern_procexec {
	int		pm_credentialschanged;
	uintfptr_t	pm_entryaddr;
};

struct pmckern_map_in {
	void		*pm_file;	/* filename or vnode pointer */
	uintfptr_t	pm_address;	/* address object is loaded at */
};

struct pmckern_map_out {
	uintfptr_t	pm_address;	/* start address of region */
	size_t		pm_size;	/* size of unmapped region */
};

/* hook */
extern int (*pmc_hook)(struct thread *_td, int _function, void *_arg);
extern int (*pmc_intr)(int _cpu, struct trapframe *_frame);

/* SX lock protecting the hook */
extern struct sx pmc_sx;

/* Per-cpu flags indicating availability of sampling data */
extern volatile cpuset_t pmc_cpumask;

/* Count of system-wide sampling PMCs in existence */
extern volatile int pmc_ss_count;

/* kernel version number */
extern const int pmc_kernel_version;

/* Hook invocation; for use within the kernel */
#define	PMC_CALL_HOOK(t, cmd, arg)		\
do {						\
	sx_slock(&pmc_sx);			\
	if (pmc_hook != NULL)			\
		(pmc_hook)((t), (cmd), (arg));	\
	sx_sunlock(&pmc_sx);			\
} while (0)

/* Hook invocation that needs an exclusive lock */
#define	PMC_CALL_HOOK_X(t, cmd, arg)		\
do {						\
	sx_xlock(&pmc_sx);			\
	if (pmc_hook != NULL)			\
		(pmc_hook)((t), (cmd), (arg));	\
	sx_xunlock(&pmc_sx);			\
} while (0)

/*
 * Some hook invocations (e.g., from context switch and clock handling
 * code) need to be lock-free.
 */
#define	PMC_CALL_HOOK_UNLOCKED(t, cmd, arg)	\
do {						\
	if (pmc_hook != NULL)			\
		(pmc_hook)((t), (cmd), (arg));	\
} while (0)

#define	PMC_SWITCH_CONTEXT(t,cmd)	PMC_CALL_HOOK_UNLOCKED(t,cmd,NULL)

/* Check if a process is using HWPMCs.*/
#define PMC_PROC_IS_USING_PMCS(p)				\
	(__predict_false(atomic_load_acq_int(&(p)->p_flag) &	\
	    P_HWPMC))

#define	PMC_SYSTEM_SAMPLING_ACTIVE()		(pmc_ss_count > 0)

/* Check if a CPU has recorded samples. */
#define	PMC_CPU_HAS_SAMPLES(C)	(__predict_false(CPU_ISSET(C, &pmc_cpumask)))

/*
 * Helper functions.
 */
int		pmc_cpu_is_disabled(int _cpu);  /* deprecated */
int		pmc_cpu_is_active(int _cpu);
int		pmc_cpu_is_present(int _cpu);
int		pmc_cpu_is_primary(int _cpu);
unsigned int	pmc_cpu_max(void);

#ifdef	INVARIANTS
int		pmc_cpu_max_active(void);
#endif

#endif /* _SYS_PMCKERN_H_ */


code:
/*-
 * Copyright (c) 2005-2007, Joseph Koshy
 * Copyright (c) 2007 The FreeBSD Foundation
 * All rights reserved.
 *
 * Portions of this software were developed by A. Joseph Koshy under
 * sponsorship from the FreeBSD Foundation and Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/pmclog.h 185363 2008-11-27 09:00:47Z jkoshy $
 */

#ifndef	_SYS_PMCLOG_H_
#define	_SYS_PMCLOG_H_

#include <sys/pmc.h>

enum pmclog_type {
	/* V1 ABI */
	PMCLOG_TYPE_CLOSELOG,
	PMCLOG_TYPE_DROPNOTIFY,
	PMCLOG_TYPE_INITIALIZE,
	PMCLOG_TYPE_MAPPINGCHANGE, /* unused in v1 */
	PMCLOG_TYPE_PCSAMPLE,
	PMCLOG_TYPE_PMCALLOCATE,
	PMCLOG_TYPE_PMCATTACH,
	PMCLOG_TYPE_PMCDETACH,
	PMCLOG_TYPE_PROCCSW,
	PMCLOG_TYPE_PROCEXEC,
	PMCLOG_TYPE_PROCEXIT,
	PMCLOG_TYPE_PROCFORK,
	PMCLOG_TYPE_SYSEXIT,
	PMCLOG_TYPE_USERDATA,
	/*
	 * V2 ABI
	 *
	 * The MAP_{IN,OUT} event types obsolete the MAPPING_CHANGE
	 * event type.  The CALLCHAIN event type obsoletes the
	 * PCSAMPLE event type.
	 */
	PMCLOG_TYPE_MAP_IN,
	PMCLOG_TYPE_MAP_OUT,
	PMCLOG_TYPE_CALLCHAIN
};

/*
 * A log entry descriptor comprises of a 32 bit header and a 64 bit
 * time stamp followed by as many 32 bit words are required to record
 * the event.
 *
 * Header field format:
 *
 *  31           24           16                                   0
 *   +------------+------------+-----------------------------------+
 *   |    MAGIC   |    TYPE    |               LENGTH              |
 *   +------------+------------+-----------------------------------+
 *
 * MAGIC 	is the constant PMCLOG_HEADER_MAGIC.
 * TYPE  	contains a value of type enum pmclog_type.
 * LENGTH	contains the length of the event record, in bytes.
 */

#define	PMCLOG_ENTRY_HEADER				\
	uint32_t		pl_header;		\
	uint32_t		pl_ts_sec;		\
	uint32_t		pl_ts_nsec;

/*
 * The following structures are used to describe the size of each kind
 * of log entry to sizeof().  To keep the compiler from adding
 * padding, the fields of each structure are aligned to their natural
 * boundaries, and the structures are marked as 'packed'.
 *
 * The actual reading and writing of the log file is always in terms
 * of 4 byte quantities.
 */

struct pmclog_callchain {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pid;
	uint32_t		pl_pmcid;
	uint32_t		pl_cpuflags;
	/* 8 byte aligned */
	uintptr_t		pl_pc[PMC_CALLCHAIN_DEPTH_MAX];
} __packed;

#define	PMC_CALLCHAIN_CPUFLAGS_TO_CPU(CF)	(((CF) >> 16) & 0xFFFF)
#define	PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(CF)	((CF) & PMC_CC_F_USERSPACE)
#define	PMC_CALLCHAIN_TO_CPUFLAGS(CPU,FLAGS)	\
	(((CPU) << 16) | ((FLAGS) & 0xFFFF))

struct pmclog_closelog {
	PMCLOG_ENTRY_HEADER
};

struct pmclog_dropnotify {
	PMCLOG_ENTRY_HEADER
};

struct pmclog_initialize {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_version;	/* driver version */
	uint32_t		pl_cpu;		/* enum pmc_cputype */
} __packed;

struct pmclog_map_in {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pid;
	uintfptr_t		pl_start;	/* 8 byte aligned */
	char			pl_pathname[PATH_MAX];
} __packed;

struct pmclog_map_out {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pid;
	uintfptr_t		pl_start;	/* 8 byte aligned */
	uintfptr_t		pl_end;
} __packed;

struct pmclog_pcsample {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pid;
	uintfptr_t		pl_pc;		/* 8 byte aligned */
	uint32_t		pl_pmcid;
	uint32_t		pl_usermode;
} __packed;

struct pmclog_pmcallocate {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pmcid;
	uint32_t		pl_event;
	uint32_t		pl_flags;
} __packed;

struct pmclog_pmcattach {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pmcid;
	uint32_t		pl_pid;
	char			pl_pathname[PATH_MAX];
} __packed;

struct pmclog_pmcdetach {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pmcid;
	uint32_t		pl_pid;
} __packed;

struct pmclog_proccsw {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pmcid;
	uint64_t		pl_value;	/* keep 8 byte aligned */
	uint32_t		pl_pid;
} __packed;

struct pmclog_procexec {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pid;
	uintfptr_t		pl_start;	/* keep 8 byte aligned */
	uint32_t		pl_pmcid;
	char			pl_pathname[PATH_MAX];
} __packed;

struct pmclog_procexit {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pmcid;
	uint64_t		pl_value;	/* keep 8 byte aligned */
	uint32_t		pl_pid;
} __packed;

struct pmclog_procfork {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_oldpid;
	uint32_t		pl_newpid;
} __packed;

struct pmclog_sysexit {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_pid;
} __packed;

struct pmclog_userdata {
	PMCLOG_ENTRY_HEADER
	uint32_t		pl_userdata;
} __packed;

union pmclog_entry {		/* only used to size scratch areas */
	struct pmclog_callchain		pl_cc;
	struct pmclog_closelog		pl_cl;
	struct pmclog_dropnotify	pl_dn;
	struct pmclog_initialize	pl_i;
	struct pmclog_map_in		pl_mi;
	struct pmclog_map_out		pl_mo;
	struct pmclog_pcsample		pl_s;
	struct pmclog_pmcallocate	pl_a;
	struct pmclog_pmcattach		pl_t;
	struct pmclog_pmcdetach		pl_d;
	struct pmclog_proccsw		pl_c;
	struct pmclog_procexec		pl_x;
	struct pmclog_procexit		pl_e;
	struct pmclog_procfork		pl_f;
	struct pmclog_sysexit		pl_se;
	struct pmclog_userdata		pl_u;
};

#define	PMCLOG_HEADER_MAGIC					0xEEU

#define	PMCLOG_HEADER_TO_LENGTH(H)				\
	((H) & 0x0000FFFF)
#define	PMCLOG_HEADER_TO_TYPE(H)				\
	(((H) & 0x00FF0000) >> 16)
#define	PMCLOG_HEADER_TO_MAGIC(H)				\
	(((H) & 0xFF000000) >> 24)
#define	PMCLOG_HEADER_CHECK_MAGIC(H)				\
	(PMCLOG_HEADER_TO_MAGIC(H) == PMCLOG_HEADER_MAGIC)

#ifdef	_KERNEL

/*
 * Prototypes
 */
int	pmclog_configure_log(struct pmc_mdep *_md, struct pmc_owner *_po,
    int _logfd);
int	pmclog_deconfigure_log(struct pmc_owner *_po);
int	pmclog_flush(struct pmc_owner *_po);
void	pmclog_initialize(void);
void	pmclog_process_callchain(struct pmc *_pm, struct pmc_sample *_ps);
void	pmclog_process_closelog(struct pmc_owner *po);
void	pmclog_process_dropnotify(struct pmc_owner *po);
void	pmclog_process_map_in(struct pmc_owner *po, pid_t pid,
    uintfptr_t start, const char *path);
void	pmclog_process_map_out(struct pmc_owner *po, pid_t pid,
    uintfptr_t start, uintfptr_t end);
void	pmclog_process_pmcallocate(struct pmc *_pm);
void	pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path);
void	pmclog_process_pmcdetach(struct pmc *_pm, pid_t _pid);
void	pmclog_process_proccsw(struct pmc *_pm, struct pmc_process *_pp,
    pmc_value_t _v);
void	pmclog_process_procexec(struct pmc_owner *_po, pmc_id_t _pmid, pid_t _pid,
    uintfptr_t _startaddr, char *_path);
void	pmclog_process_procexit(struct pmc *_pm, struct pmc_process *_pp);
void	pmclog_process_procfork(struct pmc_owner *_po, pid_t _oldpid, pid_t _newpid);
void	pmclog_process_sysexit(struct pmc_owner *_po, pid_t _pid);
int	pmclog_process_userlog(struct pmc_owner *_po,
    struct pmc_op_writelog *_wl);
void	pmclog_shutdown(void);
#endif	/* _KERNEL */

#endif	/* _SYS_PMCLOG_H_ */


code:
/*-
 * Copyright (c) 1997 Peter Wemm <peter@freebsd.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/poll.h 99710 2002-07-10 04:47:25Z mike $
 */

#ifndef _SYS_POLL_H_
#define	_SYS_POLL_H_

#include <sys/cdefs.h>

/*
 * This file is intended to be compatible with the traditional poll.h.
 */

typedef	unsigned int	nfds_t;

/*
 * This structure is passed as an array to poll(2).
 */
struct pollfd {
	int	fd;		/* which file descriptor to poll */
	short	events;		/* events we are interested in */
	short	revents;	/* events found on return */
};

/*
 * Requestable events.  If poll(2) finds any of these set, they are
 * copied to revents on return.
 * XXX Note that FreeBSD doesn't make much distinction between POLLPRI
 * and POLLRDBAND since none of the file types have distinct priority
 * bands - and only some have an urgent "mode".
 * XXX Note POLLIN isn't really supported in true SVSV terms.  Under SYSV
 * POLLIN includes all of normal, band and urgent data.  Most poll handlers
 * on FreeBSD only treat it as "normal" data.
 */
#define	POLLIN		0x0001		/* any readable data available */
#define	POLLPRI		0x0002		/* OOB/Urgent readable data */
#define	POLLOUT		0x0004		/* file descriptor is writeable */
#define	POLLRDNORM	0x0040		/* non-OOB/URG data available */
#define	POLLWRNORM	POLLOUT		/* no write type differentiation */
#define	POLLRDBAND	0x0080		/* OOB/Urgent readable data */
#define	POLLWRBAND	0x0100		/* OOB/Urgent data can be written */

#if __BSD_VISIBLE
/* General FreeBSD extension (currently only supported for sockets): */
#define	POLLINIGNEOF	0x2000		/* like POLLIN, except ignore EOF */
#endif

/*
 * These events are set if they occur regardless of whether they were
 * requested.
 */
#define	POLLERR		0x0008		/* some poll error occurred */
#define	POLLHUP		0x0010		/* file descriptor was "hung up" */
#define	POLLNVAL	0x0020		/* requested events "invalid" */

#if __BSD_VISIBLE

#define	POLLSTANDARD	(POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|\
			 POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)

/*
 * Request that poll() wait forever.
 * XXX in SYSV, this is defined in stropts.h, which is not included
 * by poll.h.
 */
#define	INFTIM		(-1)

#endif

#ifndef _KERNEL

__BEGIN_DECLS
int	poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout);
__END_DECLS

#endif /* !_KERNEL */

#endif /* !_SYS_POLL_H_ */


code:
#ifndef _P1003_1B_P1003_1B_H_
#define _P1003_1B_P1003_1B_H_
/*-
 * Copyright (c) 1996, 1997, 1998
 *	HD Associates, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by HD Associates, Inc
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/posix4.h 225617 2011-09-16 13:58:51Z kmacy $
 */

#include <sys/param.h>
#include <sys/ioccom.h>
#include <sys/malloc.h>
#include <sys/sched.h>

/* Generate syscall stubs for when something is optionally
 * loadable as a module.  References "syscall_not_present".
 * XXX Good candidate for sys/syscall.h
 */
struct proc;
struct nosys_args;
extern int syscall_not_present(struct thread *, const char *, struct nosys_args *);

#define SYSCALL_NOT_PRESENT_GEN(SC) \
int sys_ ## SC (struct thread *td, struct SC##_args *uap) \
{ \
	return syscall_not_present(td, #SC , (struct nosys_args *)uap); \
}

MALLOC_DECLARE(M_P31B);

#define p31b_malloc(SIZE) malloc((SIZE), M_P31B, M_WAITOK)
#define p31b_free(P) free((P), M_P31B)

int p31b_proc(struct proc *, pid_t, struct proc **);

void p31b_setcfg(int, int);
int p31b_getcfg(int);
int p31b_iscfg(int);
void p31b_unsetcfg(int);

#ifdef _KPOSIX_PRIORITY_SCHEDULING

/*
 * KSCHED_OP_RW is a vector of read/write flags for each entry indexed
 * by the enum ksched_op.
 *
 * 1 means you need write access, 0 means read is sufficient.
 */

enum ksched_op {

#define KSCHED_OP_RW { 1, 0, 1, 0, 0, 0, 0, 0 }

	SCHED_SETPARAM,
	SCHED_GETPARAM,
	SCHED_SETSCHEDULER,
	SCHED_GETSCHEDULER,
	SCHED_YIELD,
	SCHED_GET_PRIORITY_MAX,
	SCHED_GET_PRIORITY_MIN,
	SCHED_RR_GET_INTERVAL,
	SCHED_OP_MAX
};

struct ksched;

int ksched_attach(struct ksched **);
int ksched_detach(struct ksched *);

int ksched_setparam(struct ksched *,
	struct thread *, const struct sched_param *);
int ksched_getparam(struct ksched *,
	struct thread *, struct sched_param *);

int ksched_setscheduler(struct ksched *,
	struct thread *, int, const struct sched_param *);
int ksched_getscheduler(struct ksched *, struct thread *, int *);

int ksched_yield(struct ksched *);

int ksched_get_priority_max(struct ksched *, int, int *);
int ksched_get_priority_min(struct ksched *, int, int *);

int ksched_rr_get_interval(struct ksched *,
	struct thread *, struct timespec *);

#endif /* _KPOSIX_PRIORITY_SCHEDULING */

#endif /* _P1003_1B_P1003_1B_H_ */


code:
/*-
 * Copyright (c) 2001 Mitsuru IWASAKI
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	$FreeBSD: release/9.0.0/sys/sys/power.h 100084 2002-07-15 14:06:03Z markm $
 */

#ifndef _SYS_POWER_H_
#define _SYS_POWER_H_

#include <sys/eventhandler.h>

/* Power management system type */
#define POWER_PM_TYPE_APM		0x00
#define POWER_PM_TYPE_ACPI		0x01
#define POWER_PM_TYPE_NONE		0xff

/* Commands for Power management function */
#define POWER_CMD_SUSPEND		0x00

/* Sleep state */
#define POWER_SLEEP_STATE_STANDBY	0x00
#define POWER_SLEEP_STATE_SUSPEND	0x01
#define POWER_SLEEP_STATE_HIBERNATE	0x02

typedef int (*power_pm_fn_t)(u_long, void*, ...);
extern int	 power_pm_register(u_int, power_pm_fn_t, void *);
extern u_int	 power_pm_get_type(void);
extern void	 power_pm_suspend(int);

/*
 * System power API.
 */
#define POWER_PROFILE_PERFORMANCE        0
#define POWER_PROFILE_ECONOMY            1

extern int	power_profile_get_state(void);
extern void	power_profile_set_state(int);

typedef void (*power_profile_change_hook)(void *, int);
EVENTHANDLER_DECLARE(power_profile_change, power_profile_change_hook);

#endif	/* !_SYS_POWER_H_ */


code:
/*-
 * Copyright (c) 1994, Henrik Vestergaard Draboel
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Henrik Vestergaard Draboel.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/priority.h 221829 2011-05-13 05:27:58Z mdf $
 */

#ifndef _SYS_PRIORITY_H_
#define _SYS_PRIORITY_H_

/*
 * Process priority specifications.
 */

/*
 * Priority classes.
 */

#define	PRI_ITHD		1	/* Interrupt thread. */
#define	PRI_REALTIME		2	/* Real time process. */
#define	PRI_TIMESHARE		3	/* Time sharing process. */
#define	PRI_IDLE		4	/* Idle process. */

/*
 * PRI_FIFO is POSIX.1B SCHED_FIFO.
 */

#define	PRI_FIFO_BIT		8
#define	PRI_FIFO		(PRI_FIFO_BIT | PRI_REALTIME)

#define	PRI_BASE(P)		((P) & ~PRI_FIFO_BIT)
#define	PRI_IS_REALTIME(P)	(PRI_BASE(P) == PRI_REALTIME)
#define	PRI_NEED_RR(P)		((P) != PRI_FIFO)

/*
 * Priorities.  Note that with 64 run queues, differences less than 4 are
 * insignificant.
 */

/*
 * Priorities range from 0 to 255, but differences of less then 4 (RQ_PPQ)
 * are insignificant.  Ranges are as follows:
 *
 * Interrupt threads:		0 - 47
 * Realtime user threads:	48 - 79
 * Top half kernel threads:	80 - 119
 * Time sharing user threads:	120 - 223
 * Idle user threads:		224 - 255
 *
 * XXX If/When the specific interrupt thread and top half thread ranges
 * disappear, a larger range can be used for user processes.
 */

#define	PRI_MIN			(0)		/* Highest priority. */
#define	PRI_MAX			(255)		/* Lowest priority. */

#define	PRI_MIN_ITHD		(PRI_MIN)
#define	PRI_MAX_ITHD		(PRI_MIN_REALTIME - 1)

#define	PI_REALTIME		(PRI_MIN_ITHD + 0)
#define	PI_AV			(PRI_MIN_ITHD + 4)
#define	PI_NET			(PRI_MIN_ITHD + 8)
#define	PI_DISK			(PRI_MIN_ITHD + 12)
#define	PI_TTY			(PRI_MIN_ITHD + 16)
#define	PI_DULL			(PRI_MIN_ITHD + 20)
#define	PI_SOFT			(PRI_MIN_ITHD + 24)
#define	PI_SWI(x)		(PI_SOFT + (x) * RQ_PPQ)

#define	PRI_MIN_REALTIME	(48)
#define	PRI_MAX_REALTIME	(PRI_MIN_KERN - 1)

#define	PRI_MIN_KERN		(80)
#define	PRI_MAX_KERN		(PRI_MIN_TIMESHARE - 1)

#define	PSWP			(PRI_MIN_KERN + 0)
#define	PVM			(PRI_MIN_KERN + 4)
#define	PINOD			(PRI_MIN_KERN + 8)
#define	PRIBIO			(PRI_MIN_KERN + 12)
#define	PVFS			(PRI_MIN_KERN + 16)
#define	PZERO			(PRI_MIN_KERN + 20)
#define	PSOCK			(PRI_MIN_KERN + 24)
#define	PWAIT			(PRI_MIN_KERN + 28)
#define	PLOCK			(PRI_MIN_KERN + 32)
#define	PPAUSE			(PRI_MIN_KERN + 36)

#define	PRI_MIN_TIMESHARE	(120)
#define	PRI_MAX_TIMESHARE	(PRI_MIN_IDLE - 1)

#define	PUSER			(PRI_MIN_TIMESHARE)

#define	PRI_MIN_IDLE		(224)
#define	PRI_MAX_IDLE		(PRI_MAX)

#ifdef _KERNEL
/* Other arguments for kern_yield(9). */
#define	PRI_USER	-2	/* Change to current user priority. */
#define	PRI_UNCHANGED	-1	/* Do not change priority. */
#endif

struct priority {
	u_char	pri_class;	/* Scheduling class. */
	u_char	pri_level;	/* Normal priority level. */
	u_char	pri_native;	/* Priority before propogation. */
	u_char	pri_user;	/* User priority based on p_cpu and p_nice. */
};

#endif	/* !_SYS_PRIORITY_H_ */