From aabfc08f2cd7661d13b542d5f269f7749a4eabf5 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Thu, 3 Nov 2011 21:09:36 +0100
Subject: [PATCH 14/18] hwpmc: Remaining porting to DragonFly.

* Adjust the PMC_IN_USERSPACE macro. VM_MAX_USER_ADDRESS is an end
  address, not a max.

* fo_write(), fo_close() and fdrop() all don't take a thread argument
  in DragonFly. Nor do syscall handlers.

* psignal() -> lwpsignal()

* kproc_{create,exit} -> kthread_*

* Callchain capture is broken right now, so disable it by setting the
  depth to 1 and commenting out the tunable to modify it. Some associated
  code is brought in nevertheless.

* Adjust the CPU binding save/restore code.

* Some more lock adjustments.

* Use atomic_*_cpumask() where necessary.

* ia32_pause -> cpu_pause

* Add a struct sysmsg to the pmc_syscall_args structure (kernel).

* Move the unprivileged_syspmcs sysctl and tunable from security.bsd to
  security.

* Some more adjustments in the userland tools.

* In the manual page, remove an an unneeded config line in the SYNOPSIS.

In-collaboration-with: aggelos
---
 share/man/man4/hwpmc.4             |    5 +-
 sys/cpu/i386/include/pmc_mdep.h    |    2 +-
 sys/cpu/x86_64/include/pmc_mdep.h  |    2 +-
 sys/dev/misc/hwpmc/hwpmc_core.c    |    2 +-
 sys/dev/misc/hwpmc/hwpmc_logging.c |   29 ++++---
 sys/dev/misc/hwpmc/hwpmc_mod.c     |  155 ++++++++++++++++--------------------
 sys/dev/misc/hwpmc/hwpmc_piv.c     |    2 +-
 sys/dev/misc/hwpmc/hwpmc_x86.c     |    2 +-
 sys/kern/kern_pmc.c                |   16 +---
 sys/sys/pmc.h                      |    6 +-
 sys/sys/proc.h                     |    2 +-
 sys/sys/thread.h                   |    1 +
 usr.sbin/pmccontrol/pmccontrol.c   |    2 +
 usr.sbin/pmcstat/pmcpl_gprof.c     |    2 +
 usr.sbin/pmcstat/pmcstat.c         |    8 +-
 15 files changed, 111 insertions(+), 125 deletions(-)

diff --git a/share/man/man4/hwpmc.4 b/share/man/man4/hwpmc.4
index f797767..d81271c 100644
--- a/share/man/man4/hwpmc.4
+++ b/share/man/man4/hwpmc.4
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD: src/share/man/man4/hwpmc.4,v 1.25 2010/08/16 15:18:30 joel Exp $
 .\"
-.Dd September 22, 2008
+.Dd June 26, 2011
 .Dt HWPMC 4
 .Os
 .Sh NAME
@@ -37,9 +37,6 @@
 .Sh SYNOPSIS
 .Cd "options HWPMC_HOOKS"
 .Cd "device hwpmc"
-.Pp
-Additionally, for i386 systems:
-.Cd "device apic"
 .Sh DESCRIPTION
 The
 .Nm
diff --git a/sys/cpu/i386/include/pmc_mdep.h b/sys/cpu/i386/include/pmc_mdep.h
index a409bde..083a532 100644
--- a/sys/cpu/i386/include/pmc_mdep.h
+++ b/sys/cpu/i386/include/pmc_mdep.h
@@ -141,7 +141,7 @@ struct pmc_mdep;
 #define	PMC_IN_KERNEL(va) (((va) >= USRSTACK) &&	\
 	((va) < VM_MAX_KERNEL_ADDRESS))
 
-#define	PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
+#define	PMC_IN_USERSPACE(va) ((va) < /* XXX */ VM_MAX_USER_ADDRESS)
 
 #define	PMC_IN_TRAP_HANDLER(PC) 			\
 	((PC) >= (uintptr_t) start_exceptions &&	\
diff --git a/sys/cpu/x86_64/include/pmc_mdep.h b/sys/cpu/x86_64/include/pmc_mdep.h
index 19ab0a0..14fe682 100644
--- a/sys/cpu/x86_64/include/pmc_mdep.h
+++ b/sys/cpu/x86_64/include/pmc_mdep.h
@@ -117,7 +117,7 @@ union pmc_md_pmc {
 	(va) < DMAP_MAX_ADDRESS) || ((va) >= VM_MIN_KERNEL_ADDRESS &&	\
 	(va) < VM_MAX_KERNEL_ADDRESS))
 
-#define	PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
+#define	PMC_IN_USERSPACE(va) ((va) < /* XXX */ VM_MAX_USER_ADDRESS)
 
 /*
  * Prototypes
diff --git a/sys/dev/misc/hwpmc/hwpmc_core.c b/sys/dev/misc/hwpmc/hwpmc_core.c
index b1e21db..6969fcd 100644
--- a/sys/dev/misc/hwpmc/hwpmc_core.c
+++ b/sys/dev/misc/hwpmc/hwpmc_core.c
@@ -1817,7 +1817,7 @@ iap_read_pmc(int cpu, int ri, pmc_value_t *v)
 		*v = tmp;
 
 	PMCDBG(MDP,REA,1, "iap-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
-	    ri, *v);
+	    IAP_PMC0 + ri, *v);
 
 	return (0);
 }
diff --git a/sys/dev/misc/hwpmc/hwpmc_logging.c b/sys/dev/misc/hwpmc/hwpmc_logging.c
index 2fd7d1a..36643b6 100644
--- a/sys/dev/misc/hwpmc/hwpmc_logging.c
+++ b/sys/dev/misc/hwpmc/hwpmc_logging.c
@@ -259,9 +259,9 @@ pmclog_loop(void *arg)
 	lwkt_reltoken(&p->p_token);
 
 	PMCDBG(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
-	KASSERT(po->po_kthread == curthread->td_proc,
-	    ("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
-		po, po->po_kthread, curthread->td_proc));
+	KASSERT(po->po_kthread == curthread,
+	    ("[pmclog,%d] td mismatch po=%p po/kt=%p curthread=%p", __LINE__,
+		po, po->po_kthread, curthread));
 
 	lb = NULL;
 
@@ -316,14 +316,14 @@ pmclog_loop(void *arg)
 
 		/* switch thread credentials -- see kern_ktrace.c */
 		td->td_ucred = ownercred;
-		error = fo_write(po->po_file, &auio, ownercred, 0, td);
+		error = fo_write(po->po_file, &auio, ownercred, 0);
 		td->td_ucred = mycred;
 
 		if (error) {
 			/* XXX some errors are recoverable */
 			/* send a SIGIO to the owner and exit */
 			lwkt_gettoken(&p->p_token);
-			psignal(p, SIGIO);
+			lwpsignal(p, NULL, SIGIO);
 			lwkt_reltoken(&p->p_token);
 
 			lockmgr(&pmc_kthread_lock, LK_EXCLUSIVE);
@@ -340,7 +340,7 @@ pmclog_loop(void *arg)
 			 * Close the file to get PMCLOG_EOF error
 			 * in pmclog(3).
 			 */
-			fo_close(po->po_file, curthread);
+			fo_close(po->po_file);
 		}
 
 		lockmgr(&pmc_kthread_lock, LK_EXCLUSIVE);
@@ -374,7 +374,9 @@ pmclog_loop(void *arg)
 
 	crfree(ownercred);
 
-	kproc_exit(0);
+	wakeup(curthread);
+
+	kthread_exit();
 }
 
 /*
@@ -540,7 +542,7 @@ pmclog_stop_kthread(struct pmc_owner *po)
 	 */
 
 	if (po->po_file != NULL)
-		fo_close(po->po_file, curthread);
+		fo_close(po->po_file);
 
 	lockmgr(&pmc_kthread_lock, LK_EXCLUSIVE);
 	po->po_flags &= ~PMC_PO_OWNS_LOGFILE;
@@ -583,14 +585,15 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
 		po->po_file));
 
 	/* get a reference to the file state */
-	error = fget_write(curthread, logfd, &po->po_file);
+	/* XXX swildner: I think this doesn't work yet */
+	error = holdvnode(curthread->td_proc->p_fd, logfd, &po->po_file);
 	if (error)
 		goto error;
 
 	/* mark process as owning a log file */
 	po->po_flags |= PMC_PO_OWNS_LOGFILE;
-	error = kproc_create(pmclog_loop, po, &po->po_kthread,
-	    RFHIGHPID, 0, "hwpmc: proc(%d)", p->p_pid);
+	error = kthread_create(pmclog_loop, po, &po->po_kthread,
+	    "hwpmc: proc(%d)", p->p_pid);
 	if (error)
 		goto error;
 
@@ -617,7 +620,7 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
 	    "stopped", __LINE__, po));
 
 	if (po->po_file)
-		(void) fdrop(po->po_file, curthread);
+		(void) fdrop(po->po_file);
 	po->po_file  = NULL;	/* clear file and error state */
 	po->po_error = 0;
 
@@ -671,7 +674,7 @@ pmclog_deconfigure_log(struct pmc_owner *po)
 	}
 
 	/* drop a reference to the fd */
-	error = fdrop(po->po_file, curthread);
+	error = fdrop(po->po_file);
 	po->po_file  = NULL;
 	po->po_error = 0;
 
diff --git a/sys/dev/misc/hwpmc/hwpmc_mod.c b/sys/dev/misc/hwpmc/hwpmc_mod.c
index e24ba80..f21ec27 100644
--- a/sys/dev/misc/hwpmc/hwpmc_mod.c
+++ b/sys/dev/misc/hwpmc/hwpmc_mod.c
@@ -213,7 +213,7 @@ static void	pmc_save_cpu_binding(struct pmc_binding *pb);
 static void	pmc_select_cpu(int cpu);
 static int	pmc_start(struct pmc *pm);
 static int	pmc_stop(struct pmc *pm);
-static int	pmc_syscall_handler(struct thread *td, void *syscall_args);
+static int	pmc_syscall_handler(void *syscall_args);
 static void	pmc_unlink_target_process(struct pmc *pmc,
     struct pmc_process *pp);
 
@@ -223,8 +223,11 @@ static void	pmc_unlink_target_process(struct pmc *pmc,
 
 SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0, "HWPMC parameters");
 
+static int pmc_callchaindepth = 1;
+#if 0 /* XXX swildner: TBD */
 static int pmc_callchaindepth = PMC_CALLCHAIN_DEPTH;
 TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "callchaindepth", &pmc_callchaindepth);
+#endif
 SYSCTL_INT(_kern_hwpmc, OID_AUTO, callchaindepth, CTLFLAG_RD,
     &pmc_callchaindepth, 0, "depth of call chain records");
 
@@ -258,7 +261,7 @@ SYSCTL_INT(_kern_hwpmc, OID_AUTO, nsamples, CTLFLAG_RD,
     &pmc_nsamples, 0, "number of PC samples per CPU");
 
 /*
- * security.bsd.unprivileged_syspmcs -- allow non-root processes to
+ * security.unprivileged_syspmcs -- allow non-root processes to
  * allocate system-wide PMCs.
  *
  * Allowing unprivileged processes to allocate system PMCs is convenient
@@ -267,8 +270,8 @@ SYSCTL_INT(_kern_hwpmc, OID_AUTO, nsamples, CTLFLAG_RD,
  */
 
 static int pmc_unprivileged_syspmcs = 0;
-TUNABLE_INT("security.bsd.unprivileged_syspmcs", &pmc_unprivileged_syspmcs);
-SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_syspmcs, CTLFLAG_RW,
+TUNABLE_INT("security.unprivileged_syspmcs", &pmc_unprivileged_syspmcs);
+SYSCTL_INT(_security, OID_AUTO, unprivileged_syspmcs, CTLFLAG_RW,
     &pmc_unprivileged_syspmcs, 0,
     "allow unprivileged process to allocate system PMCs");
 
@@ -312,7 +315,7 @@ static moduledata_t pmc_mod = {
 	&pmc_syscall_mod
 };
 
-DECLARE_MODULE(pmc, pmc_mod, SI_SUB_SMP, SI_ORDER_ANY);
+DECLARE_MODULE(pmc, pmc_mod, SI_SUB_CONFIGURE, SI_ORDER_ANY);
 MODULE_VERSION(pmc, PMC_VERSION);
 
 #ifdef	DEBUG
@@ -481,6 +484,14 @@ pmc_debugflags_sysctl_handler(SYSCTL_HANDLER_ARGS)
 }
 #endif
 
+static int
+p_candebug(struct thread *td, struct proc *p)
+{
+	KKASSERT(td->td_proc != NULL);
+
+	return p_canptrace(td->td_proc, PT_ATTACH, p);
+}
+
 /*
  * Map a row index to a classdep structure and return the adjusted row
  * index for the PMC class index.
@@ -623,10 +634,7 @@ static void
 pmc_save_cpu_binding(struct pmc_binding *pb)
 {
 	PMCDBG(CPU,BND,2, "%s", "save-cpu");
-	thread_lock(curthread);
-	pb->pb_bound = sched_is_bound(curthread);
-	pb->pb_cpu   = curthread->td_oncpu;
-	thread_unlock(curthread);
+	pb->pb_cpu = mycpuid;
 	PMCDBG(CPU,BND,2, "save-cpu cpu=%d", pb->pb_cpu);
 }
 
@@ -638,13 +646,9 @@ static void
 pmc_restore_cpu_binding(struct pmc_binding *pb)
 {
 	PMCDBG(CPU,BND,2, "restore-cpu curcpu=%d restore=%d",
-	    curthread->td_oncpu, pb->pb_cpu);
-	thread_lock(curthread);
-	if (pb->pb_bound)
-		sched_bind(curthread, pb->pb_cpu);
-	else
-		sched_unbind(curthread);
-	thread_unlock(curthread);
+	    mycpuid, pb->pb_cpu);
+	if (mycpuid != pb->pb_cpu)
+		lwkt_migratecpu(pb->pb_cpu);
 	PMCDBG(CPU,BND,2, "%s", "restore-cpu done");
 }
 
@@ -663,13 +667,12 @@ pmc_select_cpu(int cpu)
 	    "CPU %d", __LINE__, cpu));
 
 	PMCDBG(CPU,SEL,2, "select-cpu cpu=%d", cpu);
-	thread_lock(curthread);
-	sched_bind(curthread, cpu);
-	thread_unlock(curthread);
 
-	KASSERT(curthread->td_oncpu == cpu,
+	lwkt_migratecpu(cpu);
+
+	KASSERT(mycpu->gd_cpuid == cpu,
 	    ("[pmc,%d] CPU not bound [cpu=%d, curr=%d]", __LINE__,
-		cpu, curthread->td_oncpu));
+		cpu, mycpu->gd_cpuid));
 
 	PMCDBG(CPU,SEL,2, "select-cpu cpu=%d ok", cpu);
 }
@@ -684,8 +687,9 @@ pmc_select_cpu(int cpu)
 static void
 pmc_force_context_switch(void)
 {
+	static int pillow;
 
-	pause("pmcctx", 1);
+	tsleep(&pillow, 0, "pmcctx", 1);
 }
 
 /*
@@ -699,7 +703,7 @@ pmc_getfilename(struct vnode *v, char **fullpath, char **freepath)
 
 	*fullpath = "unknown";
 	*freepath = NULL;
-	vn_fullpath(curthread, v, fullpath, freepath);
+	vn_fullpath(curthread->td_proc, v, fullpath, freepath, 0);
 }
 
 /*
@@ -869,7 +873,7 @@ pmc_unlink_target_process(struct pmc *pm, struct pmc_process *pp)
 	if (LIST_EMPTY(&pm->pm_targets)) {
 		p = pm->pm_owner->po_owner;
 		lwkt_gettoken(&p->p_token);
-		psignal(p, SIGIO);
+		lwpsignal(p, NULL, SIGIO);
 		lwkt_reltoken(&p->p_token);
 
 		PMCDBG(PRC,SIG,2, "signalling proc=%p signal=%d", p,
@@ -979,12 +983,10 @@ pmc_attach_one_process(struct proc *p, struct pmc *pm)
 
 	/* issue an attach event to a configured log file */
 	if (pm->pm_owner->po_flags & PMC_PO_OWNS_LOGFILE) {
+		if (!p->p_textvp)
+			return EINVAL;
 		pmc_getfilename(p->p_textvp, &fullpath, &freepath);
-		if (p->p_flag & P_KTHREAD) {
-			fullpath = kernelname;
-			freepath = NULL;
-		} else
-			pmclog_process_pmcattach(pm, p->p_pid, fullpath);
+		pmclog_process_pmcattach(pm, p->p_pid, fullpath);
 		if (freepath)
 			kfree(freepath, M_TEMP);
 		if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
@@ -1194,7 +1196,7 @@ pmc_process_csw_in(struct thread *td)
 	KASSERT(pp->pp_proc == td->td_proc,
 	    ("[pmc,%d] not my thread state", __LINE__));
 
-	cpu = PCPU_GET(cpuid); /* td->td_oncpu is invalid */
+	cpu = mycpu->gd_cpuid; /* td->td_oncpu is invalid */
 
 	PMCDBG(CSW,SWI,1, "cpu=%d proc=%p (%d, %s) pp=%p", cpu, p,
 	    p->p_pid, p->p_comm, pp);
@@ -1317,7 +1319,7 @@ pmc_process_csw_out(struct thread *td)
 	 * save PMCs
 	 */
 
-	cpu = PCPU_GET(cpuid); /* td->td_oncpu is invalid */
+	cpu = mycpu->gd_cpuid; /* td->td_oncpu is invalid */
 
 	PMCDBG(CSW,SWO,1, "cpu=%d proc=%p (%d, %s) pp=%p", cpu, p,
 	    p->p_pid, p->p_comm, pp);
@@ -1599,7 +1601,6 @@ pmc_log_kernel_mappings(struct pmc *pm)
 static void
 pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
 {
-	int locked;
 	vm_map_t map;
 	struct vnode *vp;
 	struct vmspace *vm;
@@ -1615,8 +1616,10 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
 	last_end = (vm_offset_t) 0;
 	fullpath = freepath = NULL;
 
-	if ((vm = vmspace_acquire_ref(p)) == NULL)
-		return;
+	PHOLD(p);
+	vm = p->p_vmspace;
+	sysref_get(&vm->vm_sysref);
+	PRELE(p);
 
 	map = &vm->vm_map;
 	vm_map_lock_read(map);
@@ -1632,26 +1635,20 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
 		/*
 		 * We only care about executable map entries.
 		 */
-		if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) ||
-		    !(entry->protection & VM_PROT_EXECUTE) ||
+		if (!(entry->protection & VM_PROT_EXECUTE) ||
 		    (entry->object.vm_object == NULL)) {
 			continue;
 		}
 
 		obj = entry->object.vm_object;
-		VM_OBJECT_LOCK(obj);
+		crit_enter();
 
 		/*
 		 * Walk the backing_object list to find the base
 		 * (non-shadowed) vm_object.
 		 */
-		for (lobj = tobj = obj; tobj != NULL; tobj = tobj->backing_object) {
-			if (tobj != obj)
-				VM_OBJECT_LOCK(tobj);
-			if (lobj != obj)
-				VM_OBJECT_UNLOCK(lobj);
+		for (lobj = tobj = obj; tobj != NULL; tobj = tobj->backing_object)
 			lobj = tobj;
-		}
 
 		/*
 		 * At this point lobj is the base vm_object and it is locked.
@@ -1659,14 +1656,12 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
 		if (lobj == NULL) {
 			PMCDBG(LOG,OPS,2, "hwpmc: lobj unexpectedly NULL! pid=%d "
 			    "vm_map=%p vm_obj=%p\n", p->p_pid, map, obj);
-			VM_OBJECT_UNLOCK(obj);
+			crit_exit();
 			continue;
 		}
 
 		if (lobj->type != OBJT_VNODE || lobj->handle == NULL) {
-			if (lobj != obj)
-				VM_OBJECT_UNLOCK(lobj);
-			VM_OBJECT_UNLOCK(obj);
+			crit_exit();
 			continue;
 		}
 
@@ -1677,9 +1672,7 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
 		 */
 		if (entry->start == last_end && lobj->handle == last_vp) {
 			last_end = entry->end;
-			if (lobj != obj)
-				VM_OBJECT_UNLOCK(lobj);
-			VM_OBJECT_UNLOCK(obj);
+			crit_exit();
 			continue;
 		}
 
@@ -1700,18 +1693,14 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
 
 		vp = lobj->handle;
 		vref(vp);
-		if (lobj != obj)
-			VM_OBJECT_UNLOCK(lobj);
 
-		VM_OBJECT_UNLOCK(obj);
+		crit_exit();
 
 		freepath = NULL;
 		pmc_getfilename(vp, &fullpath, &freepath);
 		last_vp = vp;
 
-		locked = VFS_LOCK_GIANT(vp->v_mount);
 		vrele(vp);
-		VFS_UNLOCK_GIANT(locked);
 
 		vp = NULL;
 		pmclog_process_map_in(po, p->p_pid, start_addr, fullpath);
@@ -1747,7 +1736,7 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
 	}
 
 	vm_map_unlock_read(map);
-	vmspace_free(vm);
+	sysref_put(&vm->vm_sysref);
 	return;
 }
 
@@ -1965,8 +1954,8 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
 		 * had already processed the interrupt).  We don't
 		 * lose the interrupt sample.
 		 */
-		atomic_clear_int(&pmc_cpumask, (1 << PCPU_GET(cpuid)));
-		pmc_process_samples(PCPU_GET(cpuid));
+		atomic_clear_cpumask(&pmc_cpumask, (1 << mycpu->gd_cpuid));
+		pmc_process_samples(mycpu->gd_cpuid);
 		break;
 
 
@@ -2000,9 +1989,9 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
 		 */
 		KASSERT(td == curthread, ("[pmc,%d] td != curthread",
 		    __LINE__));
-		pmc_capture_user_callchain(PCPU_GET(cpuid),
+		pmc_capture_user_callchain(mycpu->gd_cpuid,
 		    (struct trapframe *) arg);
-		td->td_pflags &= ~TDP_CALLCHAIN;
+		td->td_flags &= ~TDF_CALLCHAIN;
 		break;
 
 	default:
@@ -2355,7 +2344,7 @@ pmc_release_pmc_descriptor(struct pmc *pm)
 			}
 		}
 
-		cpu = curthread->td_oncpu; /* setup cpu for pmd_release() */
+		cpu = curthread->td_gd->gd_cpuid; /* setup cpu for pmd_release() */
 
 	}
 
@@ -2796,16 +2785,15 @@ static const char *pmc_op_to_name[] = {
 } while (0)
 
 static int
-pmc_syscall_handler(struct thread *td, void *syscall_args)
+pmc_syscall_handler(void *syscall_args)
 {
 	int error, is_sx_locked, op;
 	struct pmc_syscall_args *c;
 	void *arg;
+	struct thread *td = curthread;
 
 	PMC_GET_SX_XLOCK(ENOSYS);
 
-	DROP_GIANT();
-
 	is_sx_locked = 1;
 
 	c = (struct pmc_syscall_args *) syscall_args;
@@ -3302,7 +3290,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
 				    pmc_can_allocate_rowindex(
 					    curthread->td_proc, n,
 					    PMC_CPU_ANY) == 0 &&
-				    pcd->pcd_allocate_pmc(curthread->td_oncpu,
+				    pcd->pcd_allocate_pmc(curthread->td_gd->gd_cpuid,
 					adjri, pmc, &pa) == 0)
 					break;
 			}
@@ -3697,7 +3685,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
 			pcd = pmc_ri_to_classdep(md, ri, &adjri);
 
 			spin_lock(&pm->pm_lock);
-			cpu = curthread->td_oncpu;
+			cpu = curthread->td_gd->gd_cpuid;
 
 			if (prw.pm_flags & PMC_F_OLDVALUE) {
 				if ((pm->pm_flags & PMC_F_ATTACHED_TO_OWNER) &&
@@ -3910,8 +3898,6 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
 	if (error)
 		atomic_add_int(&pmc_stats.pm_syscall_errors, 1);
 
-	PICKUP_GIANT();
-
 	return error;
 }
 
@@ -3936,21 +3922,21 @@ pmc_post_callchain_callback(void)
 	/*
 	 * If there is multiple PMCs for the same interrupt ignore new post
 	 */
-	if (td->td_pflags & TDP_CALLCHAIN)
+	if (td->td_flags & TDF_CALLCHAIN)
 		return;
 
 	/*
 	 * Mark this thread as needing callchain capture.
-	 * `td->td_pflags' will be safe to touch because this thread
+	 * `td->td_flags' will be safe to touch because this thread
 	 * was in user space when it was interrupted.
 	 */
-	td->td_pflags |= TDP_CALLCHAIN;
+	td->td_flags |= TDF_CALLCHAIN;
 
 	/*
 	 * Don't let this thread migrate between CPUs until callchain
 	 * capture completes.
 	 */
-	sched_pin();
+	panic("[pmc,%d] XXX sched_pin()", __LINE__);
 
 	return;
 }
@@ -4047,7 +4033,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, struct trapframe *tf,
 
  done:
 	/* mark CPU as needing processing */
-	atomic_set_int(&pmc_cpumask, (1 << cpu));
+	atomic_set_cpumask(&pmc_cpumask, (1 << cpu));
 
 	return (error);
 }
@@ -4070,12 +4056,12 @@ pmc_capture_user_callchain(int cpu, struct trapframe *tf)
 	int ncallchains;
 #endif
 
-	sched_unpin();	/* Can migrate safely now. */
+	panic("[pmc,%d] XXX sched_unpin()", __LINE__);
 
 	psb = pmc_pcpu[cpu]->pc_sb;
 	td = curthread;
 
-	KASSERT(td->td_pflags & TDP_CALLCHAIN,
+	KASSERT(td->td_flags & TDF_CALLCHAIN,
 	    ("[pmc,%d] Retrieving callchain for thread that doesn't want it",
 		__LINE__));
 
@@ -4097,7 +4083,7 @@ pmc_capture_user_callchain(int cpu, struct trapframe *tf)
 
 		KASSERT(ps->ps_cpu == cpu,
 		    ("[pmc,%d] cpu mismatch ps_cpu=%d pcpu=%d", __LINE__,
-			ps->ps_cpu, PCPU_GET(cpuid)));
+			ps->ps_cpu, mycpu->gd_cpuid));
 
 		pm = ps->ps_pmc;
 
@@ -4138,15 +4124,14 @@ pmc_process_samples(int cpu)
 {
 	struct pmc *pm;
 	int adjri, n;
-	struct thread *td;
 	struct pmc_owner *po;
 	struct pmc_sample *ps;
 	struct pmc_classdep *pcd;
 	struct pmc_samplebuffer *psb;
 
-	KASSERT(PCPU_GET(cpuid) == cpu,
+	KASSERT(mycpu->gd_cpuid == cpu,
 	    ("[pmc,%d] not on the correct CPU pcpu=%d cpu=%d", __LINE__,
-		PCPU_GET(cpuid), cpu));
+		mycpu->gd_cpuid, cpu));
 
 	psb = pmc_pcpu[cpu]->pc_sb;
 
@@ -4157,7 +4142,7 @@ pmc_process_samples(int cpu)
 			break;
 		if (ps->ps_nsamples == PMC_SAMPLE_INUSE) {
 			/* Need a rescan at a later time. */
-			atomic_set_int(&pmc_cpumask, (1 << cpu));
+			atomic_set_cpumask(&pmc_cpumask, (1 << cpu));
 			break;
 		}
 
@@ -4189,10 +4174,8 @@ pmc_process_samples(int cpu)
 		 * would have done.
 		 */
 		if (pm->pm_flags & PMC_F_ATTACHED_TO_OWNER) {
-			if (ps->ps_flags & PMC_CC_F_USERSPACE) {
-				td = FIRST_THREAD_IN_PROC(po->po_owner);
-				addupc_intr(td, ps->ps_pc[0], 1);
-			}
+			if (ps->ps_flags & PMC_CC_F_USERSPACE)
+				addupc_intr(po->po_owner, ps->ps_pc[0], 1);
 			goto entrydone;
 		}
 
@@ -4312,7 +4295,7 @@ pmc_process_exit(void *arg __unused, struct proc *p)
 	PMCDBG(PRC,EXT,1, "process-exit proc=%p (%d, %s)", p, p->p_pid,
 	    p->p_comm);
 
-	cpu = curthread->td_oncpu;
+	cpu = curthread->td_gd->gd_cpuid;
 
 	if ((pp = pmc_find_process_descriptor(p,
 		 PMC_FLAG_REMOVE)) != NULL) {
@@ -4764,7 +4747,7 @@ pmc_cleanup(void)
 				    po->po_owner->p_comm);
 
 				lwkt_gettoken(&po->po_owner->p_token);
-				psignal(po->po_owner, SIGBUS);
+				lwpsignal(po->po_owner, NULL, SIGBUS);
 				lwkt_reltoken(&po->po_owner->p_token);
 
 				pmc_destroy_owner_descriptor(po);
diff --git a/sys/dev/misc/hwpmc/hwpmc_piv.c b/sys/dev/misc/hwpmc/hwpmc_piv.c
index 5f827a1..4fb50f7 100644
--- a/sys/dev/misc/hwpmc/hwpmc_piv.c
+++ b/sys/dev/misc/hwpmc/hwpmc_piv.c
@@ -477,7 +477,7 @@ static struct p4_cpu **p4_pcpu;
  */
 #define	P4_PCPU_ACQ_INTR_SPINLOCK(PC) do {				\
 		while (!atomic_cmpset_acq_int(&pc->pc_intrlock, 0, 1))	\
-			ia32_pause();					\
+			cpu_pause();					\
 	} while (0)
 #define	P4_PCPU_REL_INTR_SPINLOCK(PC) 					\
 	atomic_store_rel_int(&pc->pc_intrlock, 0);
diff --git a/sys/dev/misc/hwpmc/hwpmc_x86.c b/sys/dev/misc/hwpmc/hwpmc_x86.c
index 311bdb3..c438e3c 100644
--- a/sys/dev/misc/hwpmc/hwpmc_x86.c
+++ b/sys/dev/misc/hwpmc/hwpmc_x86.c
@@ -173,7 +173,7 @@ pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
 		return (1);
 
 	stackstart = (uintptr_t) td->td_kstack;
-	stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE;
+	stackend = (uintptr_t) td->td_kstack + td->td_kstack_size;
 
 	if (PMC_IN_TRAP_HANDLER(pc) ||
 	    !PMC_IN_KERNEL(pc) ||
diff --git a/sys/kern/kern_pmc.c b/sys/kern/kern_pmc.c
index 40df170..e623029 100644
--- a/sys/kern/kern_pmc.c
+++ b/sys/kern/kern_pmc.c
@@ -116,12 +116,7 @@ SYSUNINIT(pmclock, SI_SUB_DRIVERS, SI_ORDER_ANY, pmc_uninit_lock, 0);
 int
 pmc_cpu_is_active(int cpu)
 {
-#ifdef	SMP
-	return (pmc_cpu_is_present(cpu) &&
-	    (hlt_cpus_mask & (1 << cpu)) == 0);
-#else
 	return (1);
-#endif
 }
 
 /* Deprecated. */
@@ -134,21 +129,20 @@ pmc_cpu_is_disabled(int cpu)
 int
 pmc_cpu_is_present(int cpu)
 {
-#ifdef	SMP
-	return (!CPU_ABSENT(cpu));
-#else
 	return (1);
-#endif
 }
 
 int
 pmc_cpu_is_primary(int cpu)
 {
+	panic("%s: TBI", __func__);
+#if 0
 #ifdef	SMP
 	return ((logical_cpus_mask & (1 << cpu)) == 0);
 #else
 	return (1);
 #endif
+#endif
 }
 
 
@@ -161,7 +155,7 @@ unsigned int
 pmc_cpu_max(void)
 {
 #ifdef	SMP
-	return (mp_maxid+1);
+	return (ncpus);
 #else
 	return (1);
 #endif
@@ -181,7 +175,7 @@ pmc_cpu_max_active(void)
 	 * this function would change to return the current number
 	 * of "active" CPUs.
 	 */
-	return (mp_ncpus);
+	return (ncpus);
 #else
 	return (1);
 #endif
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
index e1b985f..4ffe3a0 100644
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -587,6 +587,9 @@ struct pmc_op_getmsr {
  */
 
 struct pmc_syscall_args {
+#ifdef _KERNEL
+	struct sysmsg	pmop_sysmsg;
+#endif
 	uint32_t	pmop_code;	/* one of PMC_OP_* */
 	void		*pmop_data;	/* syscall parameter */
 };
@@ -756,7 +759,7 @@ struct pmc_owner  {
 	struct spinlock		po_lock;	/* 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 thread		*po_kthread;	/* (k) helper kthread */
 	struct pmclog_buffer	*po_curbuf;	/* current log buffer */
 	struct file		*po_file;	/* file reference */
 	int			po_error;	/* recorded error */
@@ -867,7 +870,6 @@ struct pmc_cpu {
  */
 
 struct pmc_binding {
-	int	pb_bound;	/* is bound? */
 	int	pb_cpu;		/* if so, to which CPU */
 };
 
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 85b6dd6..5a734a7 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -341,7 +341,7 @@ struct	proc {
 #define	P_ADVLOCK	0x00001	/* Process may hold a POSIX advisory lock */
 #define	P_CONTROLT	0x00002	/* Has a controlling terminal */
 #define	P_SWAPPEDOUT	0x00004	/* Swapped out of memory */
-#define P_UNUSED3	0x00008
+#define	P_HWPMC         0x00008 /* Process is using HWPMCs */
 #define	P_PPWAIT	0x00010	/* Parent is waiting for child to exec/exit */
 #define	P_PROFIL	0x00020	/* Has started profiling */
 #define P_UNUSED5	0x00040 /* was: Selecting; wakeup/waiting danger */
diff --git a/sys/sys/thread.h b/sys/sys/thread.h
index b4cc199..8024035 100644
--- a/sys/sys/thread.h
+++ b/sys/sys/thread.h
@@ -368,6 +368,7 @@ struct thread {
 #define TDF_KERNELFP		0x01000000	/* kernel using fp coproc */
 #define TDF_UNUSED02000000	0x02000000
 #define TDF_CRYPTO		0x04000000	/* crypto thread */
+#define TDF_CALLCHAIN		0x08000000	/* Capture thread's callchain */
 
 #define TDF_MP_STOPREQ		0x00000001	/* suspend_kproc */
 #define TDF_MP_WAKEREQ		0x00000002	/* resume_kproc */
diff --git a/usr.sbin/pmccontrol/pmccontrol.c b/usr.sbin/pmccontrol/pmccontrol.c
index 6b43299..1d3cad0 100644
--- a/usr.sbin/pmccontrol/pmccontrol.c
+++ b/usr.sbin/pmccontrol/pmccontrol.c
@@ -146,10 +146,12 @@ pmcc_do_enable_disable(struct pmcc_op_list *op_list)
 	cpumask = (1 << ncpu) - 1;
 	dummy = sizeof(int);
 	haltedcpus = (cpumask_t) 0;
+#if 0 /* XXX swildner */
 	if (ncpu > 1 && sysctlbyname("machdep.hlt_cpus", &haltedcpus,
 	    &dummy, NULL, 0) < 0)
 		err(EX_OSERR, "ERROR: Cannot determine which CPUs are "
 		    "halted");
+#endif
 	cpumask &= ~haltedcpus;
 
 	/* Determine the maximum number of PMCs in any CPU. */
diff --git a/usr.sbin/pmcstat/pmcpl_gprof.c b/usr.sbin/pmcstat/pmcpl_gprof.c
index e710fa6..276738f 100644
--- a/usr.sbin/pmcstat/pmcpl_gprof.c
+++ b/usr.sbin/pmcstat/pmcpl_gprof.c
@@ -129,7 +129,9 @@ pmcstat_gmon_create_file(struct pmcstat_gmonfile *pgf,
 	    sizeof(struct gmonhdr);
 	gm.version = GMONVERSION;
 	gm.profrate = 0;		/* use ticks */
+#if 0 /* XXX swildner */
 	gm.histcounter_type = 0;	/* compatibility with moncontrol() */
+#endif
 	gm.spare[0] = gm.spare[1] = 0;
 
 	/* Write out the gmon header */
diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c
index 2519346..f8cc2d4 100644
--- a/usr.sbin/pmcstat/pmcstat.c
+++ b/usr.sbin/pmcstat/pmcstat.c
@@ -286,7 +286,7 @@ pmcstat_find_targets(const char *spec)
 		    errbuf)) == NULL)
 			err(EX_OSERR, "ERROR: Cannot open kernel \"%s\"",
 			    errbuf);
-		if ((pmcstat_plist = kvm_getprocs(pmcstat_kvm, KERN_PROC_PROC,
+		if ((pmcstat_plist = kvm_getprocs(pmcstat_kvm, KERN_PROC_ALL,
 		    0, &nproc)) == NULL)
 			err(EX_OSERR, "ERROR: Cannot get process list: %s",
 			    kvm_geterr(pmcstat_kvm));
@@ -300,10 +300,10 @@ pmcstat_find_targets(const char *spec)
 	}
 
 	for (n = 0, kp = pmcstat_plist; n < nproc; n++, kp++) {
-		if ((rv = regexec(&reg, kp->ki_comm, 1, &regmatch, 0)) == 0) {
+		if ((rv = regexec(&reg, kp->kp_comm, 1, &regmatch, 0)) == 0) {
 			if ((pt = malloc(sizeof(*pt))) == NULL)
 				goto outofmemory;
-			pt->pt_pid = kp->ki_pid;
+			pt->pt_pid = kp->kp_pid;
 			SLIST_INSERT_HEAD(&args.pa_targets, pt, pt_next);
 		} else if (rv != REG_NOMATCH) {
 			regerror(rv, &reg, errbuf, sizeof(errbuf));
@@ -617,6 +617,7 @@ main(int argc, char **argv)
 		err(EX_OSERR, "ERROR: Cannot determine the number of CPUs");
 	cpumask = (1 << ncpu) - 1;
 	haltedcpus = 0;
+#if 0 /* XXX swildner */
 	if (ncpu > 1) {
 		if (sysctlbyname("machdep.hlt_cpus", &haltedcpus, &dummy,
 		    NULL, 0) < 0)
@@ -624,6 +625,7 @@ main(int argc, char **argv)
 			    "halted");
 		cpumask &= ~haltedcpus;
 	}
+#endif
 
 	while ((option = getopt(argc, argv,
 	    "CD:EF:G:M:NO:P:R:S:TWc:df:gk:m:n:o:p:qr:s:t:vw:z:")) != -1)
-- 
1.7.0.5

