Quantcast

Re: svn commit: r233628 - in head: lib/libpmc sys/amd64/amd64 sys/amd64/include sys/arm/include sys/conf sys/dev/hwpmc sys/i386/i386 sys/i386/include sys/kern sys/mips/include sys/modules/hwpmc sys/pow...

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: svn commit: r233628 - in head: lib/libpmc sys/amd64/amd64 sys/amd64/include sys/arm/include sys/conf sys/dev/hwpmc sys/i386/i386 sys/i386/include sys/kern sys/mips/include sys/modules/hwpmc sys/pow...

Adrian Chadd-2
Hi Fabien,

I've heard some rumours that this broke hwpmc support for mips24k.

Monthadar, can you please provide some background info for this?

Thanks,



adrian

On 28 March 2012 13:58, Fabien Thomas <[hidden email]> wrote:

> Author: fabient
> Date: Wed Mar 28 20:58:30 2012
> New Revision: 233628
> URL: http://svn.freebsd.org/changeset/base/233628
>
> Log:
>  Add software PMC support.
>
>  New kernel events can be added at various location for sampling or counting.
>  This will for example allow easy system profiling whatever the processor is
>  with known tools like pmcstat(8).
>
>  Simultaneous usage of software PMC and hardware PMC is possible, for example
>  looking at the lock acquire failure, page fault while sampling on
>  instructions.
>
>  Sponsored by: NETASQ
>  MFC after:    1 month
>
> Added:
>  head/lib/libpmc/pmc.soft.3   (contents, props changed)
>  head/sys/dev/hwpmc/hwpmc_soft.c   (contents, props changed)
>  head/sys/dev/hwpmc/hwpmc_soft.h   (contents, props changed)
> Modified:
>  head/lib/libpmc/Makefile
>  head/lib/libpmc/libpmc.c
>  head/lib/libpmc/pmc.3
>  head/lib/libpmc/pmc.atom.3
>  head/lib/libpmc/pmc.core.3
>  head/lib/libpmc/pmc.core2.3
>  head/lib/libpmc/pmc.corei7.3
>  head/lib/libpmc/pmc.corei7uc.3
>  head/lib/libpmc/pmc.iaf.3
>  head/lib/libpmc/pmc.k7.3
>  head/lib/libpmc/pmc.k8.3
>  head/lib/libpmc/pmc.mips24k.3
>  head/lib/libpmc/pmc.octeon.3
>  head/lib/libpmc/pmc.p4.3
>  head/lib/libpmc/pmc.p5.3
>  head/lib/libpmc/pmc.p6.3
>  head/lib/libpmc/pmc.sandybridge.3
>  head/lib/libpmc/pmc.sandybridgeuc.3
>  head/lib/libpmc/pmc.tsc.3
>  head/lib/libpmc/pmc.ucf.3
>  head/lib/libpmc/pmc.westmere.3
>  head/lib/libpmc/pmc.westmereuc.3
>  head/lib/libpmc/pmc.xscale.3
>  head/lib/libpmc/pmclog.c
>  head/lib/libpmc/pmclog.h
>  head/sys/amd64/amd64/trap.c
>  head/sys/amd64/include/pmc_mdep.h
>  head/sys/arm/include/pmc_mdep.h
>  head/sys/conf/files
>  head/sys/dev/hwpmc/hwpmc_amd.c
>  head/sys/dev/hwpmc/hwpmc_core.c
>  head/sys/dev/hwpmc/hwpmc_intel.c
>  head/sys/dev/hwpmc/hwpmc_logging.c
>  head/sys/dev/hwpmc/hwpmc_mips.c
>  head/sys/dev/hwpmc/hwpmc_mod.c
>  head/sys/dev/hwpmc/hwpmc_piv.c
>  head/sys/dev/hwpmc/hwpmc_powerpc.c
>  head/sys/dev/hwpmc/hwpmc_ppro.c
>  head/sys/dev/hwpmc/hwpmc_tsc.c
>  head/sys/dev/hwpmc/hwpmc_x86.c
>  head/sys/dev/hwpmc/hwpmc_xscale.c
>  head/sys/dev/hwpmc/pmc_events.h
>  head/sys/i386/i386/trap.c
>  head/sys/i386/include/pmc_mdep.h
>  head/sys/kern/kern_clock.c
>  head/sys/kern/kern_lock.c
>  head/sys/kern/kern_mutex.c
>  head/sys/kern/kern_pmc.c
>  head/sys/kern/kern_rwlock.c
>  head/sys/kern/kern_sx.c
>  head/sys/kern/subr_trap.c
>  head/sys/mips/include/pmc_mdep.h
>  head/sys/modules/hwpmc/Makefile
>  head/sys/powerpc/include/pmc_mdep.h
>  head/sys/sys/pmc.h
>  head/sys/sys/pmckern.h
>  head/sys/sys/pmclog.h
>  head/usr.sbin/pmcstat/pmcstat_log.c
>
> Modified: head/lib/libpmc/Makefile
> ==============================================================================
> --- head/lib/libpmc/Makefile    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/Makefile    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -20,6 +20,7 @@ MAN+= pmc_read.3
>  MAN+=  pmc_set.3
>  MAN+=  pmc_start.3
>  MAN+=  pmclog.3
> +MAN+=  pmc.soft.3
>
>  # PMC-dependent manual pages
>  .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
>
> Modified: head/lib/libpmc/libpmc.c
> ==============================================================================
> --- head/lib/libpmc/libpmc.c    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/libpmc.c    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -77,11 +77,12 @@ static int tsc_allocate_pmc(enum pmc_eve
>  static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>     struct pmc_op_pmcallocate *_pmc_config);
>  #endif
> -
>  #if defined(__mips__)
>  static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>                             struct pmc_op_pmcallocate *_pmc_config);
>  #endif /* __mips__ */
> +static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
> +    struct pmc_op_pmcallocate *_pmc_config);
>
>  #if defined(__powerpc__)
>  static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec,
> @@ -156,6 +157,8 @@ PMC_CLASSDEP_TABLE(octeon, OCTEON);
>  PMC_CLASSDEP_TABLE(ucf, UCF);
>  PMC_CLASSDEP_TABLE(ppc7450, PPC7450);
>
> +static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT];
> +
>  #undef __PMC_EV_ALIAS
>  #define        __PMC_EV_ALIAS(N,CODE)  { N, PMC_EV_##CODE },
>
> @@ -215,21 +218,22 @@ static const struct pmc_event_descr west
>                PMC_CLASS_##C, __VA_ARGS__                      \
>        }
>
> -PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
> -PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
> -PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
> -PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
> -PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
> -PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
> -PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
> -PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
> -PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
> -PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC);
> -PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC);
> -PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE);
> -PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K);
> -PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_OCTEON);
> -PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_PPC7450);
> +PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
> +PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC);
> +PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
> +PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
> +PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
> +PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
> +PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC);
> +PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
> +PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC);
> +PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC);
> +PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC);
> +PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE);
> +PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K);
> +PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON);
> +PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450);
> +PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT);
>
>  static const struct pmc_event_descr tsc_event_table[] =
>  {
> @@ -279,16 +283,24 @@ PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc)
>  #if    defined(__XSCALE__)
>  PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale);
>  #endif
> -
>  #if defined(__mips__)
>  PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips);
>  PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips);
>  #endif /* __mips__ */
> -
>  #if defined(__powerpc__)
>  PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450);
>  #endif
>
> +static struct pmc_class_descr soft_class_table_descr =
> +{
> +       .pm_evc_name  = "SOFT-",
> +       .pm_evc_name_size = sizeof("SOFT-") - 1,
> +       .pm_evc_class = PMC_CLASS_SOFT,
> +       .pm_evc_event_table = NULL,
> +       .pm_evc_event_table_size = 0,
> +       .pm_evc_allocate_pmc = soft_allocate_pmc
> +};
> +
>  #undef PMC_CLASS_TABLE_DESC
>
>  static const struct pmc_class_descr **pmc_class_table;
> @@ -343,9 +355,12 @@ static const char * pmc_state_names[] =
>        __PMC_STATES()
>  };
>
> -static int pmc_syscall = -1;           /* filled in by pmc_init() */
> -
> -static struct pmc_cpuinfo cpu_info;    /* filled in by pmc_init() */
> +/*
> + * Filled in by pmc_init().
> + */
> +static int pmc_syscall = -1;
> +static struct pmc_cpuinfo cpu_info;
> +static struct pmc_op_getdyneventinfo soft_event_info;
>
>  /* Event masks for events */
>  struct pmc_masks {
> @@ -2179,6 +2194,25 @@ tsc_allocate_pmc(enum pmc_event pe, char
>  }
>  #endif
>
> +static struct pmc_event_alias generic_aliases[] = {
> +       EV_ALIAS("instructions",                "SOFT-CLOCK.HARD"),
> +       EV_ALIAS(NULL, NULL)
> +};
> +
> +static int
> +soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
> +    struct pmc_op_pmcallocate *pmc_config)
> +{
> +       (void)ctrspec;
> +       (void)pmc_config;
> +
> +       if (pe < PMC_EV_SOFT_FIRST || pe > PMC_EV_SOFT_LAST)
> +               return (-1);
> +
> +       pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
> +       return (0);
> +}
> +
>  #if    defined(__XSCALE__)
>
>  static struct pmc_event_alias xscale_aliases[] = {
> @@ -2663,6 +2697,10 @@ pmc_event_names_of_class(enum pmc_class
>                ev = ppc7450_event_table;
>                count = PMC_EVENT_TABLE_SIZE(ppc7450);
>                break;
> +       case PMC_CLASS_SOFT:
> +               ev = soft_event_table;
> +               count = soft_event_info.pm_nevent;
> +               break;
>        default:
>                errno = EINVAL;
>                return (-1);
> @@ -2676,6 +2714,7 @@ pmc_event_names_of_class(enum pmc_class
>
>        for (;count--; ev++, names++)
>                *names = ev->pm_ev_name;
> +
>        return (0);
>  }
>
> @@ -2780,11 +2819,34 @@ pmc_init(void)
>                pmc_class_table[n] = NULL;
>
>        /*
> +        * Get soft events list.
> +        */
> +       soft_event_info.pm_class = PMC_CLASS_SOFT;
> +       if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0)
> +               return (pmc_syscall = -1);
> +
> +       /* Map soft events to static list. */
> +       for (n = 0; n < soft_event_info.pm_nevent; n++) {
> +               soft_event_table[n].pm_ev_name =
> +                   soft_event_info.pm_events[n].pm_ev_name;
> +               soft_event_table[n].pm_ev_code =
> +                   soft_event_info.pm_events[n].pm_ev_code;
> +       }
> +       soft_class_table_descr.pm_evc_event_table_size = \
> +           soft_event_info.pm_nevent;
> +       soft_class_table_descr.pm_evc_event_table = \
> +           soft_event_table;
> +
> +       /*
>         * Fill in the class table.
>         */
>        n = 0;
> +
> +       /* Fill soft events information. */
> +       pmc_class_table[n++] = &soft_class_table_descr;
>  #if defined(__amd64__) || defined(__i386__)
> -       pmc_class_table[n++] = &tsc_class_table_descr;
> +       if (cpu_info.pm_cputype != PMC_CPU_GENERIC)
> +               pmc_class_table[n++] = &tsc_class_table_descr;
>
>        /*
>         * Check if this CPU has fixed function counters.
> @@ -2867,6 +2929,9 @@ pmc_init(void)
>                pmc_class_table[n] = &p4_class_table_descr;
>                break;
>  #endif
> +       case PMC_CPU_GENERIC:
> +               PMC_MDEP_INIT(generic);
> +               break;
>  #if defined(__XSCALE__)
>        case PMC_CPU_INTEL_XSCALE:
>                PMC_MDEP_INIT(xscale);
> @@ -3035,18 +3100,19 @@ _pmc_name_of_event(enum pmc_event pe, en
>                evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale);
>        } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) {
>                ev = mips24k_event_table;
> -               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k
> -);
> +               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k);
>        } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) {
>                ev = octeon_event_table;
>                evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon);
>        } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) {
>                ev = ppc7450_event_table;
> -               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450
> -);
> +               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450);
>        } else if (pe == PMC_EV_TSC_TSC) {
>                ev = tsc_event_table;
>                evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
> +       } else if (pe >= PMC_EV_SOFT_FIRST && pe <= PMC_EV_SOFT_LAST) {
> +               ev = soft_event_table;
> +               evfence = soft_event_table + soft_event_info.pm_nevent;
>        }
>
>        for (; ev != evfence; ev++)
>
> Modified: head/lib/libpmc/pmc.3
> ==============================================================================
> --- head/lib/libpmc/pmc.3       Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.3       Wed Mar 28 20:58:30 2012        (r233628)
> @@ -223,6 +223,8 @@ and
>  CPUs.
>  .It Li PMC_CLASS_TSC
>  The timestamp counter on i386 and amd64 architecture CPUs.
> +.It Li PMC_CLASS_SOFT
> +Software events.
>  .El
>  .Ss PMC Capabilities
>  Capabilities of performance monitoring hardware are denoted using
> @@ -525,6 +527,7 @@ API is
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmclog 3 ,
>  .Xr hwpmc 4 ,
>
> Modified: head/lib/libpmc/pmc.atom.3
> ==============================================================================
> --- head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:58:30 2012        (r233628)
> @@ -1176,6 +1176,7 @@ and the underlying hardware events used
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.core.3
> ==============================================================================
> --- head/lib/libpmc/pmc.core.3  Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.core.3  Wed Mar 28 20:58:30 2012        (r233628)
> @@ -792,6 +792,7 @@ may not count some transitions.
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmclog 3 ,
>  .Xr hwpmc 4
>
> Modified: head/lib/libpmc/pmc.core2.3
> ==============================================================================
> --- head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:58:30 2012        (r233628)
> @@ -1107,6 +1107,7 @@ and the underlying hardware events used.
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.corei7.3
> ==============================================================================
> --- head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:58:30 2012        (r233628)
> @@ -1559,6 +1559,7 @@ Counts number of segment register loads.
>  .Xr pmc.corei7uc 3 ,
>  .Xr pmc.westmere 3 ,
>  .Xr pmc.westmereuc 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.corei7uc.3
> ==============================================================================
> --- head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:58:30 2012        (r233628)
> @@ -863,6 +863,7 @@ refreshed or needs to go into a power do
>  .Xr pmc.corei7 3 ,
>  .Xr pmc.westmere 3 ,
>  .Xr pmc.westmereuc 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.iaf.3
> ==============================================================================
> --- head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:58:30 2012        (r233628)
> @@ -132,6 +132,7 @@ CPU, use the event specifier
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.k7.3
> ==============================================================================
> --- head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -249,6 +249,7 @@ and the underlying hardware events used.
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmclog 3 ,
>  .Xr hwpmc 4
>
> Modified: head/lib/libpmc/pmc.k8.3
> ==============================================================================
> --- head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -783,6 +783,7 @@ and the underlying hardware events used.
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmclog 3 ,
>  .Xr hwpmc 4
>
> Modified: head/lib/libpmc/pmc.mips24k.3
> ==============================================================================
> --- head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:58:30 2012        (r233628)
> @@ -392,6 +392,7 @@ and the underlying hardware events used.
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.octeon.3
> ==============================================================================
> --- head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:58:30 2012        (r233628)
> @@ -232,6 +232,7 @@ and the underlying hardware events used.
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.p4.3
> ==============================================================================
> --- head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -1208,6 +1208,7 @@ and the underlying hardware events used.
>  .Xr pmc.k8 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmclog 3 ,
>  .Xr hwpmc 4
>
> Modified: head/lib/libpmc/pmc.p5.3
> ==============================================================================
> --- head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -444,6 +444,7 @@ and the underlying hardware events used.
>  .Xr pmc.k8 3 ,
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmclog 3 ,
>  .Xr hwpmc 4
>
> Modified: head/lib/libpmc/pmc.p6.3
> ==============================================================================
> --- head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -1010,6 +1010,7 @@ and the underlying hardware events used.
>  .Xr pmc.k8 3 ,
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmclog 3 ,
>  .Xr hwpmc 4
>
> Modified: head/lib/libpmc/pmc.sandybridge.3
> ==============================================================================
> --- head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:58:30 2012        (r233628)
> @@ -907,6 +907,7 @@ Split locks in SQ.
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
>  .Xr pmc.sandybridgeuc 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc.ucf 3 ,
>  .Xr pmc.westmere 3 ,
>
> Modified: head/lib/libpmc/pmc.sandybridgeuc.3
> ==============================================================================
> --- head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:58:30 2012        (r233628)
> @@ -208,6 +208,7 @@ Counts the number of core-outgoing entri
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
>  .Xr pmc.sandybridge 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc.ucf 3 ,
>  .Xr pmc.westmere 3 ,
>
> Added: head/lib/libpmc/pmc.soft.3
> ==============================================================================
> --- /dev/null   00:00:00 1970   (empty, because file is newly added)
> +++ head/lib/libpmc/pmc.soft.3  Wed Mar 28 20:58:30 2012        (r233628)
> @@ -0,0 +1,104 @@
> +.\" Copyright (c) 2012 Fabien Thomas.  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$
> +.\"
> +.Dd March 28, 2012
> +.Os
> +.Dt PMC.SOFT 3
> +.Sh NAME
> +.Nm pmc.soft
> +.Nd measurements using software based events
> +.Sh LIBRARY
> +.Lb libpmc
> +.Sh SYNOPSIS
> +.In pmc.h
> +.Sh DESCRIPTION
> +Software events are used to collect various source of software events.
> +.Ss PMC Features
> +16 sampling counters using software events based on various sources.
> +These PMCs support the following capabilities:
> +.Bl -column "PMC_CAP_INTERRUPT" "Support"
> +.It Em Capability Ta Em Support
> +.It PMC_CAP_CASCADE Ta \&No
> +.It PMC_CAP_EDGE Ta \&No
> +.It PMC_CAP_INTERRUPT Ta Yes
> +.It PMC_CAP_INVERT Ta \&No
> +.It PMC_CAP_READ Ta Yes
> +.It PMC_CAP_PRECISE Ta \&No
> +.It PMC_CAP_SYSTEM Ta Yes
> +.It PMC_CAP_TAGGING Ta \&No
> +.It PMC_CAP_THRESHOLD Ta \&No
> +.It PMC_CAP_USER Ta Yes
> +.It PMC_CAP_WRITE Ta Yes
> +.El
> +.Ss Event Qualifiers
> +There is no supported event qualifier.
> +.Pp
> +The event specifiers supported by software are:
> +.Bl -tag -width indent
> +.It Li CLOCK.HARD
> +Hard clock ticks.
> +.It Li CLOCK.STAT
> +Stat clock ticks.
> +.It Li LOCK.FAILED
> +Lock acquisition failed.
> +.It Li PAGE_FAULT.ALL
> +All page fault type.
> +.It Li PAGE_FAULT.READ
> +Read page fault.
> +.It Li PAGE_FAULT.WRITE
> +Write page fault.
> +.El
> +.Sh SEE ALSO
> +.Xr pmc 3 ,
> +.Xr pmc.atom 3 ,
> +.Xr pmc.core 3 ,
> +.Xr pmc.iaf 3 ,
> +.Xr pmc.ucf 3 ,
> +.Xr pmc.k7 3 ,
> +.Xr pmc.k8 3 ,
> +.Xr pmc.p4 3 ,
> +.Xr pmc.p5 3 ,
> +.Xr pmc.p6 3 ,
> +.Xr pmc.corei7 3 ,
> +.Xr pmc.corei7uc 3 ,
> +.Xr pmc.westmereuc 3 ,
> +.Xr pmc.tsc 3 ,
> +.Xr pmc_cpuinfo 3 ,
> +.Xr pmclog 3 ,
> +.Xr hwpmc 4
> +.Sh HISTORY
> +The
> +.Nm pmc
> +library first appeared in
> +.Fx 6.0 .
> +.Sh AUTHORS
> +The
> +.Lb libpmc
> +library was written by
> +.An "Joseph Koshy"
> +.Aq [hidden email] .
> +Software PMC was written by
> +.An "Fabien Thomas"
> +.Aq [hidden email] .
>
> Modified: head/lib/libpmc/pmc.tsc.3
> ==============================================================================
> --- head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:58:30 2012        (r233628)
> @@ -68,6 +68,7 @@ maps to the TSC.
>  .Xr pmc.p4 3 ,
>  .Xr pmc.p5 3 ,
>  .Xr pmc.p6 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmclog 3 ,
>  .Xr hwpmc 4
>  .Sh HISTORY
>
> Modified: head/lib/libpmc/pmc.ucf.3
> ==============================================================================
> --- head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:58:30 2012        (r233628)
> @@ -96,6 +96,7 @@ offset C0H under device number 0 and Fun
>  .Xr pmc.corei7uc 3 ,
>  .Xr pmc.westmere 3 ,
>  .Xr pmc.westmereuc 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.westmere.3
> ==============================================================================
> --- head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:58:30 2012        (r233628)
> @@ -1381,6 +1381,7 @@ Counts number of SID integer 64 bit shif
>  .Xr pmc.corei7 3 ,
>  .Xr pmc.corei7uc 3 ,
>  .Xr pmc.westmereuc 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.westmereuc.3
> ==============================================================================
> --- head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -1066,6 +1066,7 @@ disabled.
>  .Xr pmc.corei7 3 ,
>  .Xr pmc.corei7uc 3 ,
>  .Xr pmc.westmere 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr pmc.tsc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
>
> Modified: head/lib/libpmc/pmc.xscale.3
> ==============================================================================
> --- head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:58:30 2012        (r233628)
> @@ -134,6 +134,7 @@ and the underlying hardware events used.
>  .Xr pmc 3 ,
>  .Xr pmc_cpuinfo 3 ,
>  .Xr pmclog 3 ,
> +.Xr pmc.soft 3 ,
>  .Xr hwpmc 4
>  .Sh HISTORY
>  The
>
> Modified: head/lib/libpmc/pmclog.c
> ==============================================================================
> --- head/lib/libpmc/pmclog.c    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmclog.c    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -369,6 +369,12 @@ pmclog_get_event(void *cookie, char **da
>                    == NULL)
>                        goto error;
>                break;
> +       case PMCLOG_TYPE_PMCALLOCATEDYN:
> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_pmcid);
> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_event);
> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_flags);
> +               PMCLOG_READSTRING(le,ev->pl_u.pl_ad.pl_evname,PMC_NAME_MAX);
> +               break;
>        case PMCLOG_TYPE_PMCATTACH:
>                PMCLOG_GET_PATHLEN(pathlen,evlen,pmclog_pmcattach);
>                PMCLOG_READ32(le,ev->pl_u.pl_t.pl_pmcid);
>
> Modified: head/lib/libpmc/pmclog.h
> ==============================================================================
> --- head/lib/libpmc/pmclog.h    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/lib/libpmc/pmclog.h    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -88,6 +88,13 @@ struct pmclog_ev_pmcallocate {
>        pmc_id_t        pl_pmcid;
>  };
>
> +struct pmclog_ev_pmcallocatedyn {
> +       uint32_t        pl_event;
> +       char            pl_evname[PMC_NAME_MAX];
> +       uint32_t        pl_flags;
> +       pmc_id_t        pl_pmcid;
> +};
> +
>  struct pmclog_ev_pmcattach {
>        pmc_id_t        pl_pmcid;
>        pid_t           pl_pid;
> @@ -146,6 +153,7 @@ struct pmclog_ev {
>                struct pmclog_ev_map_out        pl_mo;
>                struct pmclog_ev_pcsample       pl_s;
>                struct pmclog_ev_pmcallocate    pl_a;
> +               struct pmclog_ev_pmcallocatedyn pl_ad;
>                struct pmclog_ev_pmcattach      pl_t;
>                struct pmclog_ev_pmcdetach      pl_d;
>                struct pmclog_ev_proccsw        pl_c;
>
> Modified: head/sys/amd64/amd64/trap.c
> ==============================================================================
> --- head/sys/amd64/amd64/trap.c Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/amd64/amd64/trap.c Wed Mar 28 20:58:30 2012        (r233628)
> @@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
>  #include <sys/vmmeter.h>
>  #ifdef HWPMC_HOOKS
>  #include <sys/pmckern.h>
> +PMC_SOFT_DEFINE( , , page_fault, all);
> +PMC_SOFT_DEFINE( , , page_fault, read);
> +PMC_SOFT_DEFINE( , , page_fault, write);
>  #endif
>
>  #include <vm/vm.h>
> @@ -743,8 +746,20 @@ trap_pfault(frame, usermode)
>                 */
>                rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
>        }
> -       if (rv == KERN_SUCCESS)
> +       if (rv == KERN_SUCCESS) {
> +#ifdef HWPMC_HOOKS
> +               if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
> +                       PMC_SOFT_CALL_TF( , , page_fault, all, frame);
> +                       if (ftype == VM_PROT_READ)
> +                               PMC_SOFT_CALL_TF( , , page_fault, read,
> +                                   frame);
> +                       else
> +                               PMC_SOFT_CALL_TF( , , page_fault, write,
> +                                   frame);
> +               }
> +#endif
>                return (0);
> +       }
>  nogo:
>        if (!usermode) {
>                if (td->td_intr_nesting_level == 0 &&
>
> Modified: head/sys/amd64/include/pmc_mdep.h
> ==============================================================================
> --- head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:58:30 2012        (r233628)
> @@ -50,13 +50,13 @@ struct pmc_mdep;
>  * measurement architecture have PMCs of the following classes: TSC,
>  * IAF, IAP, UCF and UCP.
>  */
> -#define        PMC_MDEP_CLASS_INDEX_TSC        0
> -#define        PMC_MDEP_CLASS_INDEX_K8         1
> -#define        PMC_MDEP_CLASS_INDEX_P4         1
> -#define        PMC_MDEP_CLASS_INDEX_IAP        1
> -#define        PMC_MDEP_CLASS_INDEX_IAF        2
> -#define        PMC_MDEP_CLASS_INDEX_UCP        3
> -#define        PMC_MDEP_CLASS_INDEX_UCF        4
> +#define        PMC_MDEP_CLASS_INDEX_TSC        1
> +#define        PMC_MDEP_CLASS_INDEX_K8         2
> +#define        PMC_MDEP_CLASS_INDEX_P4         2
> +#define        PMC_MDEP_CLASS_INDEX_IAP        2
> +#define        PMC_MDEP_CLASS_INDEX_IAF        3
> +#define        PMC_MDEP_CLASS_INDEX_UCP        4
> +#define        PMC_MDEP_CLASS_INDEX_UCF        5
>
>  /*
>  * On the amd64 platform we support the following PMCs.
> @@ -119,6 +119,15 @@ union pmc_md_pmc {
>
>  #define        PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
>
> +/* Build a fake kernel trapframe from current instruction pointer. */
> +#define PMC_FAKE_TRAPFRAME(TF)                                         \
> +       do {                                                            \
> +       (TF)->tf_cs = 0; (TF)->tf_rflags = 0;                           \
> +       __asm __volatile("movq %%rbp,%0" : "=r" ((TF)->tf_rbp));        \
> +       __asm __volatile("movq %%rsp,%0" : "=r" ((TF)->tf_rsp));        \
> +       __asm __volatile("call 1f \n\t1: pop %0" : "=r"((TF)->tf_rip)); \
> +       } while (0)
> +
>  /*
>  * Prototypes
>  */
>
> Modified: head/sys/arm/include/pmc_mdep.h
> ==============================================================================
> --- head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:58:30 2012        (r233628)
> @@ -29,7 +29,7 @@
>  #ifndef _MACHINE_PMC_MDEP_H_
>  #define        _MACHINE_PMC_MDEP_H_
>
> -#define        PMC_MDEP_CLASS_INDEX_XSCALE     0
> +#define        PMC_MDEP_CLASS_INDEX_XSCALE     1
>  /*
>  * On the ARM platform we support the following PMCs.
>  *
>
> Modified: head/sys/conf/files
> ==============================================================================
> --- head/sys/conf/files Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/conf/files Wed Mar 28 20:58:30 2012        (r233628)
> @@ -1260,6 +1260,7 @@ dev/hme/if_hme_sbus.c             optional hme sbus
>  dev/hptiop/hptiop.c            optional hptiop scbus
>  dev/hwpmc/hwpmc_logging.c      optional hwpmc
>  dev/hwpmc/hwpmc_mod.c          optional hwpmc
> +dev/hwpmc/hwpmc_soft.c         optional hwpmc
>  dev/ichsmb/ichsmb.c            optional ichsmb
>  dev/ichsmb/ichsmb_pci.c                optional ichsmb pci
>  dev/ida/ida.c                  optional ida
>
> Modified: head/sys/dev/hwpmc/hwpmc_amd.c
> ==============================================================================
> --- head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:58:30 2012        (r233628)
> @@ -687,7 +687,8 @@ amd_intr(int cpu, struct trapframe *tf)
>                wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
>
>                /* Restart the counter if logging succeeded. */
> -               error = pmc_process_interrupt(cpu, pm, tf, TRAPF_USERMODE(tf));
> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
> +                   TRAPF_USERMODE(tf));
>                if (error == 0)
>                        wrmsr(evsel, config | AMD_PMC_ENABLE);
>        }
> @@ -874,7 +875,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int c
>  struct pmc_mdep *
>  pmc_amd_initialize(void)
>  {
> -       int classindex, error, i, nclasses, ncpus;
> +       int classindex, error, i, ncpus;
>        struct pmc_classdep *pcd;
>        enum pmc_cputype cputype;
>        struct pmc_mdep *pmc_mdep;
> @@ -926,12 +927,9 @@ pmc_amd_initialize(void)
>         * These processors have two classes of PMCs: the TSC and
>         * programmable PMCs.
>         */
> -       nclasses = 2;
> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses * sizeof (struct pmc_classdep),
> -           M_PMC, M_WAITOK|M_ZERO);
> +       pmc_mdep = pmc_mdep_alloc(2);
>
>        pmc_mdep->pmd_cputype = cputype;
> -       pmc_mdep->pmd_nclass  = nclasses;
>
>        ncpus = pmc_cpu_max();
>
>
> Modified: head/sys/dev/hwpmc/hwpmc_core.c
> ==============================================================================
> --- head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:58:30 2012        (r233628)
> @@ -2239,7 +2239,7 @@ core_intr(int cpu, struct trapframe *tf)
>                if (pm->pm_state != PMC_STATE_RUNNING)
>                        continue;
>
> -               error = pmc_process_interrupt(cpu, pm, tf,
> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>                    TRAPF_USERMODE(tf));
>
>                v = pm->pm_sc.pm_reloadcount;
> @@ -2326,7 +2326,7 @@ core2_intr(int cpu, struct trapframe *tf
>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>                        continue;
>
> -               error = pmc_process_interrupt(cpu, pm, tf,
> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>                    TRAPF_USERMODE(tf));
>                if (error)
>                        intrenable &= ~flag;
> @@ -2354,7 +2354,7 @@ core2_intr(int cpu, struct trapframe *tf
>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>                        continue;
>
> -               error = pmc_process_interrupt(cpu, pm, tf,
> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>                    TRAPF_USERMODE(tf));
>                if (error)
>                        intrenable &= ~flag;
>
> Modified: head/sys/dev/hwpmc/hwpmc_intel.c
> ==============================================================================
> --- head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:58:30 2012        (r233628)
> @@ -162,12 +162,10 @@ pmc_intel_initialize(void)
>                return (NULL);
>        }
>
> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses *
> -           sizeof(struct pmc_classdep), M_PMC, M_WAITOK|M_ZERO);
> +       /* Allocate base class and initialize machine dependent struct */
> +       pmc_mdep = pmc_mdep_alloc(nclasses);
>
>        pmc_mdep->pmd_cputype    = cputype;
> -       pmc_mdep->pmd_nclass     = nclasses;
> -
>        pmc_mdep->pmd_switch_in  = intel_switch_in;
>        pmc_mdep->pmd_switch_out = intel_switch_out;
>
>
> Modified: head/sys/dev/hwpmc/hwpmc_logging.c
> ==============================================================================
> --- head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:58:30 2012        (r233628)
> @@ -129,6 +129,7 @@ static struct mtx pmc_kthread_mtx;  /* sl
>
>  /* Emit a string.  Caution: does NOT update _le, so needs to be last */
>  #define        PMCLOG_EMITSTRING(S,L)  do { bcopy((S), _le, (L)); } while (0)
> +#define        PMCLOG_EMITNULLSTRING(L) do { bzero(_le, (L)); } while (0)
>
>  #define        PMCLOG_DESPATCH(PO)                                             \
>                pmclog_release((PO));                                   \
> @@ -835,16 +836,33 @@ void
>  pmclog_process_pmcallocate(struct pmc *pm)
>  {
>        struct pmc_owner *po;
> +       struct pmc_soft *ps;
>
>        po = pm->pm_owner;
>
>        PMCDBG(LOG,ALL,1, "pm=%p", pm);
>
> -       PMCLOG_RESERVE(po, PMCALLOCATE, sizeof(struct pmclog_pmcallocate));
> -       PMCLOG_EMIT32(pm->pm_id);
> -       PMCLOG_EMIT32(pm->pm_event);
> -       PMCLOG_EMIT32(pm->pm_flags);
> -       PMCLOG_DESPATCH(po);
> +       if (PMC_TO_CLASS(pm) == PMC_CLASS_SOFT) {
> +               PMCLOG_RESERVE(po, PMCALLOCATEDYN,
> +                   sizeof(struct pmclog_pmcallocatedyn));
> +               PMCLOG_EMIT32(pm->pm_id);
> +               PMCLOG_EMIT32(pm->pm_event);
> +               PMCLOG_EMIT32(pm->pm_flags);
> +               ps = pmc_soft_ev_acquire(pm->pm_event);
> +               if (ps != NULL)
> +                       PMCLOG_EMITSTRING(ps->ps_ev.pm_ev_name,PMC_NAME_MAX);
> +               else
> +                       PMCLOG_EMITNULLSTRING(PMC_NAME_MAX);
> +               pmc_soft_ev_release(ps);
> +               PMCLOG_DESPATCH(po);
> +       } else {
> +               PMCLOG_RESERVE(po, PMCALLOCATE,
> +                   sizeof(struct pmclog_pmcallocate));
> +               PMCLOG_EMIT32(pm->pm_id);
> +               PMCLOG_EMIT32(pm->pm_event);
> +               PMCLOG_EMIT32(pm->pm_flags);
> +               PMCLOG_DESPATCH(po);
> +       }
>  }
>
>  void
>
> Modified: head/sys/dev/hwpmc/hwpmc_mips.c
> ==============================================================================
> --- head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:58:30 2012        (r233628)
> @@ -287,7 +287,7 @@ mips_pmc_intr(int cpu, struct trapframe
>                retval = 1;
>                if (pm->pm_state != PMC_STATE_RUNNING)
>                        continue;
> -               error = pmc_process_interrupt(cpu, pm, tf,
> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>                    TRAPF_USERMODE(tf));
>                if (error) {
>                        /* Clear/disable the relevant counter */
>
> Modified: head/sys/dev/hwpmc/hwpmc_mod.c
> ==============================================================================
> --- head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:49:11 2012        (r233627)
> +++ head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:58:30 2012        (r233628)
> @@ -70,6 +70,8 @@ __FBSDID("$FreeBSD$");
>  #include <vm/vm_map.h>
>  #include <vm/vm_object.h>
>
> +#include "hwpmc_soft.h"
> +
>  /*
>  * Types
>  */
> @@ -182,7 +184,7 @@ static int  pmc_attach_one_process(struct
>  static int     pmc_can_allocate_rowindex(struct proc *p, unsigned int ri,
>     int cpu);
>  static int     pmc_can_attach(struct pmc *pm, struct proc *p);
> -static void    pmc_capture_user_callchain(int cpu, struct trapframe *tf);
> +static void    pmc_capture_user_callchain(int cpu, int soft, struct trapframe *tf);
>  static void    pmc_cleanup(void);
>  static int     pmc_detach_process(struct proc *p, struct pmc *pm);
>  static int     pmc_detach_one_process(struct proc *p, struct pmc *pm,
> @@ -206,7 +208,7 @@ static void pmc_process_csw_out(struct t
>  static void    pmc_process_exit(void *arg, struct proc *p);
>  static void    pmc_process_fork(void *arg, struct proc *p1,
>     struct proc *p2, int n);
> -static void    pmc_process_samples(int cpu);
> +static void    pmc_process_samples(int cpu, int soft);
>  static void    pmc_release_pmc_descriptor(struct pmc *pmc);
>  static void    pmc_remove_owner(struct pmc_owner *po);
>  static void    pmc_remove_process_descriptor(struct pmc_process *pp);
> @@ -218,12 +220,16 @@ static int        pmc_stop(struct pmc *pm);
>  static int     pmc_syscall_handler(struct thread *td, void *syscall_args);
>  static void    pmc_unlink_target_process(struct pmc *pmc,
>     struct pmc_process *pp);
> +static int generic_switch_in(struct pmc_cpu *pc, struct pmc_process *pp);
> +static int generic_switch_out(struct pmc_cpu *pc, struct pmc_process *pp);
> +static struct pmc_mdep *pmc_generic_cpu_initialize(void);
> +static void pmc_generic_cpu_finalize(struct pmc_mdep *md);
>
>  /*
>  * Kernel tunables and sysctl(8) interface.
>  */
>
> -SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0, "HWPMC parameters");
> +SYSCTL_DECL(_kern_hwpmc);
>
>  static int pmc_callchaindepth = PMC_CALLCHAIN_DEPTH;
>  TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "callchaindepth", &pmc_callchaindepth);
> @@ -1833,7 +1839,9 @@ const char *pmc_hooknames[] = {
>        "KLDUNLOAD",
>        "MMAP",
>        "MUNMAP",
> -       "CALLCHAIN"
> +       "CALLCHAIN-NMI",
> +       "CALLCHAIN-SOFT",
> +       "SOFTSAMPLING"
>  };
>  #endif
>
> @@ -1992,7 +2000,8 @@ pmc_hook_handler(struct thread *td, int
>                 * lose the interrupt sample.
>                 */
>                CPU_CLR_ATOMIC(PCPU_GET(cpuid), &pmc_cpumask);
> -               pmc_process_samples(PCPU_GET(cpuid));
> +               pmc_process_samples(PCPU_GET(cpuid), PMC_HR);
> +               pmc_process_samples(PCPU_GET(cpuid), PMC_SR);
>                break;
>
>
> @@ -2022,11 +2031,30 @@ pmc_hook_handler(struct thread *td, int
>                 */
>                KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>                    __LINE__));
> -               pmc_capture_user_callchain(PCPU_GET(cpuid),
> +
> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_HR,
>                    (struct trapframe *) arg);
>                td->td_pflags &= ~TDP_CALLCHAIN;
>                break;
>
> +       case PMC_FN_USER_CALLCHAIN_SOFT:
> +               /*
> +                * Record a call chain.
> +                */
> +               KASSERT(td == curthread, ("[pmc,%d] td != curthread",
> +                   __LINE__));
> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_SR,
> +                   (struct trapframe *) arg);
> +               td->td_pflags &= ~TDP_CALLCHAIN;
> +               break;
> +
> +       case PMC_FN_SOFT_SAMPLING:
> +               /*
> +                * Call soft PMC sampling intr.
> +                */
> +               pmc_soft_intr((struct pmckern_soft *) arg);
> +               break;
> +
>        default:
>  #ifdef DEBUG
>                KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
> @@ -2221,18 +2249,17 @@ pmc_destroy_pmc_descriptor(struct pmc *p
>  static void
>  pmc_wait_for_pmc_idle(struct pmc *pm)
>  {
> -#ifdef DEBUG
> +#ifdef DEBUG
>        volatile int maxloop;
>
>        maxloop = 100 * pmc_cpu_max();
>  #endif
> -
>        /*
>         * Loop (with a forced context switch) till the PMC's runcount
>         * comes down to zero.
>         */
>        while (atomic_load_acq_32(&pm->pm_runcount) > 0) {
> -#ifdef DEBUG
> +#ifdef DEBUG
>                maxloop--;
>                KASSERT(maxloop > 0,
>                    ("[pmc,%d] (ri%d, rc%d) waiting too long for "
> @@ -2972,6 +2999,53 @@ pmc_syscall_handler(struct thread *td, v
>        }
>        break;
>
> +       /*
> +        * Retrieve soft events list.
> +        */
> +       case PMC_OP_GETDYNEVENTINFO:
> +       {
> +               enum pmc_class                  cl;
> +               enum pmc_event                  ev;
> +               struct pmc_op_getdyneventinfo   *gei;
> +               struct pmc_dyn_event_descr      dev;
> +               struct pmc_soft                 *ps;
> +               uint32_t                        nevent;
> +
> +               sx_assert(&pmc_sx, SX_LOCKED);
> +
> +               gei = (struct pmc_op_getdyneventinfo *) arg;
> +
> +               if ((error = copyin(&gei->pm_class, &cl, sizeof(cl))) != 0)
> +                       break;
> +
> +               /* Only SOFT class is dynamic. */
> +               if (cl != PMC_CLASS_SOFT) {
> +                       error = EINVAL;
> +                       break;
> +               }
> +
> +               nevent = 0;
> +               for (ev = PMC_EV_SOFT_FIRST; ev <= PMC_EV_SOFT_LAST; ev++) {
> +                       ps = pmc_soft_ev_acquire(ev);
> +                       if (ps == NULL)
> +                               continue;
> +                       bcopy(&ps->ps_ev, &dev, sizeof(dev));
> +                       pmc_soft_ev_release(ps);
> +
> +                       error = copyout(&dev,
> +                           &gei->pm_events[nevent],
> +                           sizeof(struct pmc_dyn_event_descr));
> +                       if (error != 0)
> +                               break;
> +                       nevent++;
> +               }
> +               if (error != 0)
> +                       break;
> +
> +               error = copyout(&nevent, &gei->pm_nevent,
>
> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[hidden email] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-mips
To unsubscribe, send any mail to "[hidden email]"
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: svn commit: r233628 - in head: lib/libpmc sys/amd64/amd64 sys/amd64/include sys/arm/include sys/conf sys/dev/hwpmc sys/i386/i386 sys/i386/include sys/kern sys/mips/include sys/modules/hwpmc sys/pow...

Monthadar Al Jaberi
On Mon, Apr 23, 2012 at 8:44 AM, Adrian Chadd <[hidden email]> wrote:
> Hi Fabien,
>
> I've heard some rumours that this broke hwpmc support for mips24k.
>
> Monthadar, can you please provide some background info for this?
>

This is the log output

Using default protocol (TFTP)
Entry point: 0x80050100, address range: 0x80050000-0x804f1dcc
RedBoot> exec
Now booting linux kernel:
 Base address 0x80050000 Entry 0x80050100
 memsize=0x08000000
 modetty0=0,n,8,1,hw
 board=RouterStation PRO
 ethaddr=00.15.6d.c8.c9.2e
CPU platform: Atheros AR7161 rev 2
CPU Frequency=720 MHz
CPU DDR Frequency=360 MHz
CPU AHB Frequency=180 MHz
platform frequency: 720000000
arguments:
  a0 = 00000002
  a1 = 80050028
  a2 = 80050000
  a3 = 00000001
Cmd line:  �������m���������������_}������߾q��������������������������������߿���������_�w���������?-����{������~��
Environment:
  memsize = 0x08000000
  modetty0 = 0,n,8,1,hw
  ethaddr = 00.15.6d.c8.c9.2e
  board = RouterStation PRO
Cache info:
  picache_stride    = 4096
  picache_loopcount = 16
  pdcache_stride    = 4096
  pdcache_loopcount = 8
cpu0: MIPS Technologies processor v116.147
  MMU: Standard TLB, 16 entries
  L1 i-cache: 4 ways of 512 sets, 32 bytes per line
  L1 d-cache: 4 ways of 256 sets, 32 bytes per line
  Config1=0x9ee3519e<PerfCount,WatchRegs,MIPS16,EJTAG>
  Config3=0x20
KDB: debugger backends: ddb
KDB: current backend: ddb
Copyright (c) 1992-2012 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 10.0-CURRENT #12: Fri Apr 20 18:03:16 CEST 2012
    root@freebsd-re-9:/usr/obj/mips.mips/usr/src/sys/RSPRO_USB_PROD mips
WARNING: WITNESS option enabled, expect reduced performance.
MEMGUARD DEBUGGING ALLOCATOR INITIALIZED:
        MEMGUARD map base: 0xc0800000
        MEMGUARD map limit: 0xc1c00000
        MEMGUARD map size: 20480 KBytes
real memory  = 134217728 (131072K bytes)
avail memory = 123117568 (117MB)
random device not loaded; using insecure entropy
nexus0: <MIPS32 root nexus>
clock0: <Generic MIPS32 ticker> on nexus0
Timecounter "MIPS32" frequency 360000000 Hz quality 800
Event timer "MIPS32" frequency 360000000 Hz quality 800
apb0 at irq 4 on nexus0
uart0: <16550 or compatible> on apb0
uart0: console (115200,n,8,1)
gpio0: <Atheros AR71XX GPIO driver> on apb0
gpio0: [GIANT-LOCKED]
gpio0: gpio pinmask=0x0
gpioc0: <GPIO controller> on gpio0
gpiobus0: <GPIO bus> on gpio0
ehci0: <AR71XX Integrated USB 2.0 controller> at mem
0x1b000000-0x1bffffff irq 1 on nexus0
usbus0: set host controller mode
usbus0: EHCI version 1.0
usbus0: set host controller mode
usbus0 on ehci0
pcib0 at irq 0 on nexus0
pci0: <PCI bus> on pcib0
pci0: <old, non-VGA display device> at device 0.0 (no driver attached)
ath0: <Atheros 5413> irq 0 at device 17.0 on pci0
ath0: AR5413 mac 10.5 RF5413 phy 6.1
ath0: 2GHz radio: 0x0000; 5GHz radio: 0x0063
arge0: <Atheros AR71xx built-in ethernet interface> at mem
0x19000000-0x19000fff irq 2 on nexus0
arge0: No PHY specified, using mask 16
miibus0: <MII bus> on arge0
ukphy0: <Generic IEEE 802.3u media interface> PHY 4 on miibus0
ukphy0:  none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX,
1000baseT-FDX, 1000baseT-FDX-master, auto
arge0: Ethernet address: 00:15:6d:c8:c9:2e
arge1: <Atheros AR71xx built-in ethernet interface> at mem
0x1a000000-0x1a000fff irq 3 on nexus0
arge1: No PHY specified, using mask 15
arge1: Ethernet address: 00:15:6d:c8:c9:2f
spi0: <AR71XX SPI> at mem 0x1f000000-0x1f00000f on nexus0
spibus0: <spibus bus> on spi0
mx25l0: <M25Pxx Flash Family> at cs 0 on spibus0
mx25l0: mx25ll128, sector 65536 bytes, 256 sectors
ar71xx_wdog0: <Atheros AR71XX watchdog timer> on nexus0
Timecounters tick every 1.000 msec
usbus0: 480Mbps High Speed USB v2.0
ugen0.1: <Atheros> at usbus0
uhub0: <Atheros EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus0
panic: [pmc,4816] npmc miscomputed: ri=0, md->npmc=2
KDB: enter: panic
[ thread pid 0 tid 100000 ]
Stopped at      kdb_enter+0x4c: lui     at,0x8050
db> tr
Tracing pid 0 tid 100000 td 0x804f76d0
db_trace_thread+30 (?,?,?,?) ra 8068b94800000018 sp 0 sz 0
80075adc+114 (0,?,ffffffff,?) ra 8068b96000000020 sp 100000000 sz 1
80074e24+388 (?,?,?,?) ra 8068b980000000a8 sp 0 sz 0
db_command_loop+70 (?,?,?,?) ra 8068ba2800000018 sp 0 sz 0
80077900+f4 (?,?,?,?) ra 8068ba40000001a8 sp 0 sz 0
kdb_trap+110 (?,?,?,?) ra 8068bbe800000030 sp 0 sz 0
trap+c7c (?,?,?,?) ra 8068bc18000000b8 sp 0 sz 0
MipsKernGenException+134 (0,4,8043b1d4,119) ra 8068bcd0000000c8 sp
100000001 sz 1
kdb_enter+4c (?,?,?,?) ra 8068bd9800000018 sp 0 sz 0
panic+11c (?,12d0,0,2) ra 8068bdb000000028 sp 1 sz 1
800e8ca8+274 (?,?,?,?) ra 8068bdd800000038 sp 0 sz 0
syscall_module_handler+b8 (?,?,?,?) ra 8068be1000000028 sp 0 sz 0
module_register_init+9c (?,?,?,?) ra 8068be3800000028 sp 0 sz 0
mi_startup+138 (?,?,?,?) ra 8068be6000000020 sp 0 sz 0
_start+90 (?,?,?,?) ra 8068be8000000000 sp 0 sz 0
pid 0
db>

> Thanks,
>
>
>
> adrian
>
> On 28 March 2012 13:58, Fabien Thomas <[hidden email]> wrote:
>> Author: fabient
>> Date: Wed Mar 28 20:58:30 2012
>> New Revision: 233628
>> URL: http://svn.freebsd.org/changeset/base/233628
>>
>> Log:
>>  Add software PMC support.
>>
>>  New kernel events can be added at various location for sampling or counting.
>>  This will for example allow easy system profiling whatever the processor is
>>  with known tools like pmcstat(8).
>>
>>  Simultaneous usage of software PMC and hardware PMC is possible, for example
>>  looking at the lock acquire failure, page fault while sampling on
>>  instructions.
>>
>>  Sponsored by: NETASQ
>>  MFC after:    1 month
>>
>> Added:
>>  head/lib/libpmc/pmc.soft.3   (contents, props changed)
>>  head/sys/dev/hwpmc/hwpmc_soft.c   (contents, props changed)
>>  head/sys/dev/hwpmc/hwpmc_soft.h   (contents, props changed)
>> Modified:
>>  head/lib/libpmc/Makefile
>>  head/lib/libpmc/libpmc.c
>>  head/lib/libpmc/pmc.3
>>  head/lib/libpmc/pmc.atom.3
>>  head/lib/libpmc/pmc.core.3
>>  head/lib/libpmc/pmc.core2.3
>>  head/lib/libpmc/pmc.corei7.3
>>  head/lib/libpmc/pmc.corei7uc.3
>>  head/lib/libpmc/pmc.iaf.3
>>  head/lib/libpmc/pmc.k7.3
>>  head/lib/libpmc/pmc.k8.3
>>  head/lib/libpmc/pmc.mips24k.3
>>  head/lib/libpmc/pmc.octeon.3
>>  head/lib/libpmc/pmc.p4.3
>>  head/lib/libpmc/pmc.p5.3
>>  head/lib/libpmc/pmc.p6.3
>>  head/lib/libpmc/pmc.sandybridge.3
>>  head/lib/libpmc/pmc.sandybridgeuc.3
>>  head/lib/libpmc/pmc.tsc.3
>>  head/lib/libpmc/pmc.ucf.3
>>  head/lib/libpmc/pmc.westmere.3
>>  head/lib/libpmc/pmc.westmereuc.3
>>  head/lib/libpmc/pmc.xscale.3
>>  head/lib/libpmc/pmclog.c
>>  head/lib/libpmc/pmclog.h
>>  head/sys/amd64/amd64/trap.c
>>  head/sys/amd64/include/pmc_mdep.h
>>  head/sys/arm/include/pmc_mdep.h
>>  head/sys/conf/files
>>  head/sys/dev/hwpmc/hwpmc_amd.c
>>  head/sys/dev/hwpmc/hwpmc_core.c
>>  head/sys/dev/hwpmc/hwpmc_intel.c
>>  head/sys/dev/hwpmc/hwpmc_logging.c
>>  head/sys/dev/hwpmc/hwpmc_mips.c
>>  head/sys/dev/hwpmc/hwpmc_mod.c
>>  head/sys/dev/hwpmc/hwpmc_piv.c
>>  head/sys/dev/hwpmc/hwpmc_powerpc.c
>>  head/sys/dev/hwpmc/hwpmc_ppro.c
>>  head/sys/dev/hwpmc/hwpmc_tsc.c
>>  head/sys/dev/hwpmc/hwpmc_x86.c
>>  head/sys/dev/hwpmc/hwpmc_xscale.c
>>  head/sys/dev/hwpmc/pmc_events.h
>>  head/sys/i386/i386/trap.c
>>  head/sys/i386/include/pmc_mdep.h
>>  head/sys/kern/kern_clock.c
>>  head/sys/kern/kern_lock.c
>>  head/sys/kern/kern_mutex.c
>>  head/sys/kern/kern_pmc.c
>>  head/sys/kern/kern_rwlock.c
>>  head/sys/kern/kern_sx.c
>>  head/sys/kern/subr_trap.c
>>  head/sys/mips/include/pmc_mdep.h
>>  head/sys/modules/hwpmc/Makefile
>>  head/sys/powerpc/include/pmc_mdep.h
>>  head/sys/sys/pmc.h
>>  head/sys/sys/pmckern.h
>>  head/sys/sys/pmclog.h
>>  head/usr.sbin/pmcstat/pmcstat_log.c
>>
>> Modified: head/lib/libpmc/Makefile
>> ==============================================================================
>> --- head/lib/libpmc/Makefile    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/Makefile    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -20,6 +20,7 @@ MAN+= pmc_read.3
>>  MAN+=  pmc_set.3
>>  MAN+=  pmc_start.3
>>  MAN+=  pmclog.3
>> +MAN+=  pmc.soft.3
>>
>>  # PMC-dependent manual pages
>>  .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
>>
>> Modified: head/lib/libpmc/libpmc.c
>> ==============================================================================
>> --- head/lib/libpmc/libpmc.c    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/libpmc.c    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -77,11 +77,12 @@ static int tsc_allocate_pmc(enum pmc_eve
>>  static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>>     struct pmc_op_pmcallocate *_pmc_config);
>>  #endif
>> -
>>  #if defined(__mips__)
>>  static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>>                             struct pmc_op_pmcallocate *_pmc_config);
>>  #endif /* __mips__ */
>> +static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>> +    struct pmc_op_pmcallocate *_pmc_config);
>>
>>  #if defined(__powerpc__)
>>  static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>> @@ -156,6 +157,8 @@ PMC_CLASSDEP_TABLE(octeon, OCTEON);
>>  PMC_CLASSDEP_TABLE(ucf, UCF);
>>  PMC_CLASSDEP_TABLE(ppc7450, PPC7450);
>>
>> +static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT];
>> +
>>  #undef __PMC_EV_ALIAS
>>  #define        __PMC_EV_ALIAS(N,CODE)  { N, PMC_EV_##CODE },
>>
>> @@ -215,21 +218,22 @@ static const struct pmc_event_descr west
>>                PMC_CLASS_##C, __VA_ARGS__                      \
>>        }
>>
>> -PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
>> -PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
>> -PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
>> -PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>> -PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>> -PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>> -PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
>> -PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
>> -PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
>> -PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC);
>> -PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC);
>> -PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE);
>> -PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K);
>> -PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_OCTEON);
>> -PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_PPC7450);
>> +PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
>> +PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>> +PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
>> +PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>> +PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>> +PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>> +PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>> +PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>> +PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>> +PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>> +PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>> +PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE);
>> +PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K);
>> +PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON);
>> +PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450);
>> +PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT);
>>
>>  static const struct pmc_event_descr tsc_event_table[] =
>>  {
>> @@ -279,16 +283,24 @@ PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc)
>>  #if    defined(__XSCALE__)
>>  PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale);
>>  #endif
>> -
>>  #if defined(__mips__)
>>  PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips);
>>  PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips);
>>  #endif /* __mips__ */
>> -
>>  #if defined(__powerpc__)
>>  PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450);
>>  #endif
>>
>> +static struct pmc_class_descr soft_class_table_descr =
>> +{
>> +       .pm_evc_name  = "SOFT-",
>> +       .pm_evc_name_size = sizeof("SOFT-") - 1,
>> +       .pm_evc_class = PMC_CLASS_SOFT,
>> +       .pm_evc_event_table = NULL,
>> +       .pm_evc_event_table_size = 0,
>> +       .pm_evc_allocate_pmc = soft_allocate_pmc
>> +};
>> +
>>  #undef PMC_CLASS_TABLE_DESC
>>
>>  static const struct pmc_class_descr **pmc_class_table;
>> @@ -343,9 +355,12 @@ static const char * pmc_state_names[] =
>>        __PMC_STATES()
>>  };
>>
>> -static int pmc_syscall = -1;           /* filled in by pmc_init() */
>> -
>> -static struct pmc_cpuinfo cpu_info;    /* filled in by pmc_init() */
>> +/*
>> + * Filled in by pmc_init().
>> + */
>> +static int pmc_syscall = -1;
>> +static struct pmc_cpuinfo cpu_info;
>> +static struct pmc_op_getdyneventinfo soft_event_info;
>>
>>  /* Event masks for events */
>>  struct pmc_masks {
>> @@ -2179,6 +2194,25 @@ tsc_allocate_pmc(enum pmc_event pe, char
>>  }
>>  #endif
>>
>> +static struct pmc_event_alias generic_aliases[] = {
>> +       EV_ALIAS("instructions",                "SOFT-CLOCK.HARD"),
>> +       EV_ALIAS(NULL, NULL)
>> +};
>> +
>> +static int
>> +soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
>> +    struct pmc_op_pmcallocate *pmc_config)
>> +{
>> +       (void)ctrspec;
>> +       (void)pmc_config;
>> +
>> +       if (pe < PMC_EV_SOFT_FIRST || pe > PMC_EV_SOFT_LAST)
>> +               return (-1);
>> +
>> +       pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
>> +       return (0);
>> +}
>> +
>>  #if    defined(__XSCALE__)
>>
>>  static struct pmc_event_alias xscale_aliases[] = {
>> @@ -2663,6 +2697,10 @@ pmc_event_names_of_class(enum pmc_class
>>                ev = ppc7450_event_table;
>>                count = PMC_EVENT_TABLE_SIZE(ppc7450);
>>                break;
>> +       case PMC_CLASS_SOFT:
>> +               ev = soft_event_table;
>> +               count = soft_event_info.pm_nevent;
>> +               break;
>>        default:
>>                errno = EINVAL;
>>                return (-1);
>> @@ -2676,6 +2714,7 @@ pmc_event_names_of_class(enum pmc_class
>>
>>        for (;count--; ev++, names++)
>>                *names = ev->pm_ev_name;
>> +
>>        return (0);
>>  }
>>
>> @@ -2780,11 +2819,34 @@ pmc_init(void)
>>                pmc_class_table[n] = NULL;
>>
>>        /*
>> +        * Get soft events list.
>> +        */
>> +       soft_event_info.pm_class = PMC_CLASS_SOFT;
>> +       if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0)
>> +               return (pmc_syscall = -1);
>> +
>> +       /* Map soft events to static list. */
>> +       for (n = 0; n < soft_event_info.pm_nevent; n++) {
>> +               soft_event_table[n].pm_ev_name =
>> +                   soft_event_info.pm_events[n].pm_ev_name;
>> +               soft_event_table[n].pm_ev_code =
>> +                   soft_event_info.pm_events[n].pm_ev_code;
>> +       }
>> +       soft_class_table_descr.pm_evc_event_table_size = \
>> +           soft_event_info.pm_nevent;
>> +       soft_class_table_descr.pm_evc_event_table = \
>> +           soft_event_table;
>> +
>> +       /*
>>         * Fill in the class table.
>>         */
>>        n = 0;
>> +
>> +       /* Fill soft events information. */
>> +       pmc_class_table[n++] = &soft_class_table_descr;
>>  #if defined(__amd64__) || defined(__i386__)
>> -       pmc_class_table[n++] = &tsc_class_table_descr;
>> +       if (cpu_info.pm_cputype != PMC_CPU_GENERIC)
>> +               pmc_class_table[n++] = &tsc_class_table_descr;
>>
>>        /*
>>         * Check if this CPU has fixed function counters.
>> @@ -2867,6 +2929,9 @@ pmc_init(void)
>>                pmc_class_table[n] = &p4_class_table_descr;
>>                break;
>>  #endif
>> +       case PMC_CPU_GENERIC:
>> +               PMC_MDEP_INIT(generic);
>> +               break;
>>  #if defined(__XSCALE__)
>>        case PMC_CPU_INTEL_XSCALE:
>>                PMC_MDEP_INIT(xscale);
>> @@ -3035,18 +3100,19 @@ _pmc_name_of_event(enum pmc_event pe, en
>>                evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale);
>>        } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) {
>>                ev = mips24k_event_table;
>> -               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k
>> -);
>> +               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k);
>>        } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) {
>>                ev = octeon_event_table;
>>                evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon);
>>        } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) {
>>                ev = ppc7450_event_table;
>> -               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450
>> -);
>> +               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450);
>>        } else if (pe == PMC_EV_TSC_TSC) {
>>                ev = tsc_event_table;
>>                evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
>> +       } else if (pe >= PMC_EV_SOFT_FIRST && pe <= PMC_EV_SOFT_LAST) {
>> +               ev = soft_event_table;
>> +               evfence = soft_event_table + soft_event_info.pm_nevent;
>>        }
>>
>>        for (; ev != evfence; ev++)
>>
>> Modified: head/lib/libpmc/pmc.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.3       Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.3       Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -223,6 +223,8 @@ and
>>  CPUs.
>>  .It Li PMC_CLASS_TSC
>>  The timestamp counter on i386 and amd64 architecture CPUs.
>> +.It Li PMC_CLASS_SOFT
>> +Software events.
>>  .El
>>  .Ss PMC Capabilities
>>  Capabilities of performance monitoring hardware are denoted using
>> @@ -525,6 +527,7 @@ API is
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmclog 3 ,
>>  .Xr hwpmc 4 ,
>>
>> Modified: head/lib/libpmc/pmc.atom.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -1176,6 +1176,7 @@ and the underlying hardware events used
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.core.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.core.3  Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.core.3  Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -792,6 +792,7 @@ may not count some transitions.
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmclog 3 ,
>>  .Xr hwpmc 4
>>
>> Modified: head/lib/libpmc/pmc.core2.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -1107,6 +1107,7 @@ and the underlying hardware events used.
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.corei7.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -1559,6 +1559,7 @@ Counts number of segment register loads.
>>  .Xr pmc.corei7uc 3 ,
>>  .Xr pmc.westmere 3 ,
>>  .Xr pmc.westmereuc 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.corei7uc.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -863,6 +863,7 @@ refreshed or needs to go into a power do
>>  .Xr pmc.corei7 3 ,
>>  .Xr pmc.westmere 3 ,
>>  .Xr pmc.westmereuc 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.iaf.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -132,6 +132,7 @@ CPU, use the event specifier
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.k7.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -249,6 +249,7 @@ and the underlying hardware events used.
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmclog 3 ,
>>  .Xr hwpmc 4
>>
>> Modified: head/lib/libpmc/pmc.k8.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -783,6 +783,7 @@ and the underlying hardware events used.
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmclog 3 ,
>>  .Xr hwpmc 4
>>
>> Modified: head/lib/libpmc/pmc.mips24k.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -392,6 +392,7 @@ and the underlying hardware events used.
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.octeon.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -232,6 +232,7 @@ and the underlying hardware events used.
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.p4.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -1208,6 +1208,7 @@ and the underlying hardware events used.
>>  .Xr pmc.k8 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmclog 3 ,
>>  .Xr hwpmc 4
>>
>> Modified: head/lib/libpmc/pmc.p5.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -444,6 +444,7 @@ and the underlying hardware events used.
>>  .Xr pmc.k8 3 ,
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmclog 3 ,
>>  .Xr hwpmc 4
>>
>> Modified: head/lib/libpmc/pmc.p6.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -1010,6 +1010,7 @@ and the underlying hardware events used.
>>  .Xr pmc.k8 3 ,
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmclog 3 ,
>>  .Xr hwpmc 4
>>
>> Modified: head/lib/libpmc/pmc.sandybridge.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -907,6 +907,7 @@ Split locks in SQ.
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>>  .Xr pmc.sandybridgeuc 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc.ucf 3 ,
>>  .Xr pmc.westmere 3 ,
>>
>> Modified: head/lib/libpmc/pmc.sandybridgeuc.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -208,6 +208,7 @@ Counts the number of core-outgoing entri
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>>  .Xr pmc.sandybridge 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc.ucf 3 ,
>>  .Xr pmc.westmere 3 ,
>>
>> Added: head/lib/libpmc/pmc.soft.3
>> ==============================================================================
>> --- /dev/null   00:00:00 1970   (empty, because file is newly added)
>> +++ head/lib/libpmc/pmc.soft.3  Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -0,0 +1,104 @@
>> +.\" Copyright (c) 2012 Fabien Thomas.  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$
>> +.\"
>> +.Dd March 28, 2012
>> +.Os
>> +.Dt PMC.SOFT 3
>> +.Sh NAME
>> +.Nm pmc.soft
>> +.Nd measurements using software based events
>> +.Sh LIBRARY
>> +.Lb libpmc
>> +.Sh SYNOPSIS
>> +.In pmc.h
>> +.Sh DESCRIPTION
>> +Software events are used to collect various source of software events.
>> +.Ss PMC Features
>> +16 sampling counters using software events based on various sources.
>> +These PMCs support the following capabilities:
>> +.Bl -column "PMC_CAP_INTERRUPT" "Support"
>> +.It Em Capability Ta Em Support
>> +.It PMC_CAP_CASCADE Ta \&No
>> +.It PMC_CAP_EDGE Ta \&No
>> +.It PMC_CAP_INTERRUPT Ta Yes
>> +.It PMC_CAP_INVERT Ta \&No
>> +.It PMC_CAP_READ Ta Yes
>> +.It PMC_CAP_PRECISE Ta \&No
>> +.It PMC_CAP_SYSTEM Ta Yes
>> +.It PMC_CAP_TAGGING Ta \&No
>> +.It PMC_CAP_THRESHOLD Ta \&No
>> +.It PMC_CAP_USER Ta Yes
>> +.It PMC_CAP_WRITE Ta Yes
>> +.El
>> +.Ss Event Qualifiers
>> +There is no supported event qualifier.
>> +.Pp
>> +The event specifiers supported by software are:
>> +.Bl -tag -width indent
>> +.It Li CLOCK.HARD
>> +Hard clock ticks.
>> +.It Li CLOCK.STAT
>> +Stat clock ticks.
>> +.It Li LOCK.FAILED
>> +Lock acquisition failed.
>> +.It Li PAGE_FAULT.ALL
>> +All page fault type.
>> +.It Li PAGE_FAULT.READ
>> +Read page fault.
>> +.It Li PAGE_FAULT.WRITE
>> +Write page fault.
>> +.El
>> +.Sh SEE ALSO
>> +.Xr pmc 3 ,
>> +.Xr pmc.atom 3 ,
>> +.Xr pmc.core 3 ,
>> +.Xr pmc.iaf 3 ,
>> +.Xr pmc.ucf 3 ,
>> +.Xr pmc.k7 3 ,
>> +.Xr pmc.k8 3 ,
>> +.Xr pmc.p4 3 ,
>> +.Xr pmc.p5 3 ,
>> +.Xr pmc.p6 3 ,
>> +.Xr pmc.corei7 3 ,
>> +.Xr pmc.corei7uc 3 ,
>> +.Xr pmc.westmereuc 3 ,
>> +.Xr pmc.tsc 3 ,
>> +.Xr pmc_cpuinfo 3 ,
>> +.Xr pmclog 3 ,
>> +.Xr hwpmc 4
>> +.Sh HISTORY
>> +The
>> +.Nm pmc
>> +library first appeared in
>> +.Fx 6.0 .
>> +.Sh AUTHORS
>> +The
>> +.Lb libpmc
>> +library was written by
>> +.An "Joseph Koshy"
>> +.Aq [hidden email] .
>> +Software PMC was written by
>> +.An "Fabien Thomas"
>> +.Aq [hidden email] .
>>
>> Modified: head/lib/libpmc/pmc.tsc.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -68,6 +68,7 @@ maps to the TSC.
>>  .Xr pmc.p4 3 ,
>>  .Xr pmc.p5 3 ,
>>  .Xr pmc.p6 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmclog 3 ,
>>  .Xr hwpmc 4
>>  .Sh HISTORY
>>
>> Modified: head/lib/libpmc/pmc.ucf.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -96,6 +96,7 @@ offset C0H under device number 0 and Fun
>>  .Xr pmc.corei7uc 3 ,
>>  .Xr pmc.westmere 3 ,
>>  .Xr pmc.westmereuc 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.westmere.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -1381,6 +1381,7 @@ Counts number of SID integer 64 bit shif
>>  .Xr pmc.corei7 3 ,
>>  .Xr pmc.corei7uc 3 ,
>>  .Xr pmc.westmereuc 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.westmereuc.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -1066,6 +1066,7 @@ disabled.
>>  .Xr pmc.corei7 3 ,
>>  .Xr pmc.corei7uc 3 ,
>>  .Xr pmc.westmere 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr pmc.tsc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>>
>> Modified: head/lib/libpmc/pmc.xscale.3
>> ==============================================================================
>> --- head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -134,6 +134,7 @@ and the underlying hardware events used.
>>  .Xr pmc 3 ,
>>  .Xr pmc_cpuinfo 3 ,
>>  .Xr pmclog 3 ,
>> +.Xr pmc.soft 3 ,
>>  .Xr hwpmc 4
>>  .Sh HISTORY
>>  The
>>
>> Modified: head/lib/libpmc/pmclog.c
>> ==============================================================================
>> --- head/lib/libpmc/pmclog.c    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmclog.c    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -369,6 +369,12 @@ pmclog_get_event(void *cookie, char **da
>>                    == NULL)
>>                        goto error;
>>                break;
>> +       case PMCLOG_TYPE_PMCALLOCATEDYN:
>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_pmcid);
>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_event);
>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_flags);
>> +               PMCLOG_READSTRING(le,ev->pl_u.pl_ad.pl_evname,PMC_NAME_MAX);
>> +               break;
>>        case PMCLOG_TYPE_PMCATTACH:
>>                PMCLOG_GET_PATHLEN(pathlen,evlen,pmclog_pmcattach);
>>                PMCLOG_READ32(le,ev->pl_u.pl_t.pl_pmcid);
>>
>> Modified: head/lib/libpmc/pmclog.h
>> ==============================================================================
>> --- head/lib/libpmc/pmclog.h    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/lib/libpmc/pmclog.h    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -88,6 +88,13 @@ struct pmclog_ev_pmcallocate {
>>        pmc_id_t        pl_pmcid;
>>  };
>>
>> +struct pmclog_ev_pmcallocatedyn {
>> +       uint32_t        pl_event;
>> +       char            pl_evname[PMC_NAME_MAX];
>> +       uint32_t        pl_flags;
>> +       pmc_id_t        pl_pmcid;
>> +};
>> +
>>  struct pmclog_ev_pmcattach {
>>        pmc_id_t        pl_pmcid;
>>        pid_t           pl_pid;
>> @@ -146,6 +153,7 @@ struct pmclog_ev {
>>                struct pmclog_ev_map_out        pl_mo;
>>                struct pmclog_ev_pcsample       pl_s;
>>                struct pmclog_ev_pmcallocate    pl_a;
>> +               struct pmclog_ev_pmcallocatedyn pl_ad;
>>                struct pmclog_ev_pmcattach      pl_t;
>>                struct pmclog_ev_pmcdetach      pl_d;
>>                struct pmclog_ev_proccsw        pl_c;
>>
>> Modified: head/sys/amd64/amd64/trap.c
>> ==============================================================================
>> --- head/sys/amd64/amd64/trap.c Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/amd64/amd64/trap.c Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
>>  #include <sys/vmmeter.h>
>>  #ifdef HWPMC_HOOKS
>>  #include <sys/pmckern.h>
>> +PMC_SOFT_DEFINE( , , page_fault, all);
>> +PMC_SOFT_DEFINE( , , page_fault, read);
>> +PMC_SOFT_DEFINE( , , page_fault, write);
>>  #endif
>>
>>  #include <vm/vm.h>
>> @@ -743,8 +746,20 @@ trap_pfault(frame, usermode)
>>                 */
>>                rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
>>        }
>> -       if (rv == KERN_SUCCESS)
>> +       if (rv == KERN_SUCCESS) {
>> +#ifdef HWPMC_HOOKS
>> +               if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
>> +                       PMC_SOFT_CALL_TF( , , page_fault, all, frame);
>> +                       if (ftype == VM_PROT_READ)
>> +                               PMC_SOFT_CALL_TF( , , page_fault, read,
>> +                                   frame);
>> +                       else
>> +                               PMC_SOFT_CALL_TF( , , page_fault, write,
>> +                                   frame);
>> +               }
>> +#endif
>>                return (0);
>> +       }
>>  nogo:
>>        if (!usermode) {
>>                if (td->td_intr_nesting_level == 0 &&
>>
>> Modified: head/sys/amd64/include/pmc_mdep.h
>> ==============================================================================
>> --- head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -50,13 +50,13 @@ struct pmc_mdep;
>>  * measurement architecture have PMCs of the following classes: TSC,
>>  * IAF, IAP, UCF and UCP.
>>  */
>> -#define        PMC_MDEP_CLASS_INDEX_TSC        0
>> -#define        PMC_MDEP_CLASS_INDEX_K8         1
>> -#define        PMC_MDEP_CLASS_INDEX_P4         1
>> -#define        PMC_MDEP_CLASS_INDEX_IAP        1
>> -#define        PMC_MDEP_CLASS_INDEX_IAF        2
>> -#define        PMC_MDEP_CLASS_INDEX_UCP        3
>> -#define        PMC_MDEP_CLASS_INDEX_UCF        4
>> +#define        PMC_MDEP_CLASS_INDEX_TSC        1
>> +#define        PMC_MDEP_CLASS_INDEX_K8         2
>> +#define        PMC_MDEP_CLASS_INDEX_P4         2
>> +#define        PMC_MDEP_CLASS_INDEX_IAP        2
>> +#define        PMC_MDEP_CLASS_INDEX_IAF        3
>> +#define        PMC_MDEP_CLASS_INDEX_UCP        4
>> +#define        PMC_MDEP_CLASS_INDEX_UCF        5
>>
>>  /*
>>  * On the amd64 platform we support the following PMCs.
>> @@ -119,6 +119,15 @@ union pmc_md_pmc {
>>
>>  #define        PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
>>
>> +/* Build a fake kernel trapframe from current instruction pointer. */
>> +#define PMC_FAKE_TRAPFRAME(TF)                                         \
>> +       do {                                                            \
>> +       (TF)->tf_cs = 0; (TF)->tf_rflags = 0;                           \
>> +       __asm __volatile("movq %%rbp,%0" : "=r" ((TF)->tf_rbp));        \
>> +       __asm __volatile("movq %%rsp,%0" : "=r" ((TF)->tf_rsp));        \
>> +       __asm __volatile("call 1f \n\t1: pop %0" : "=r"((TF)->tf_rip)); \
>> +       } while (0)
>> +
>>  /*
>>  * Prototypes
>>  */
>>
>> Modified: head/sys/arm/include/pmc_mdep.h
>> ==============================================================================
>> --- head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -29,7 +29,7 @@
>>  #ifndef _MACHINE_PMC_MDEP_H_
>>  #define        _MACHINE_PMC_MDEP_H_
>>
>> -#define        PMC_MDEP_CLASS_INDEX_XSCALE     0
>> +#define        PMC_MDEP_CLASS_INDEX_XSCALE     1
>>  /*
>>  * On the ARM platform we support the following PMCs.
>>  *
>>
>> Modified: head/sys/conf/files
>> ==============================================================================
>> --- head/sys/conf/files Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/conf/files Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -1260,6 +1260,7 @@ dev/hme/if_hme_sbus.c             optional hme sbus
>>  dev/hptiop/hptiop.c            optional hptiop scbus
>>  dev/hwpmc/hwpmc_logging.c      optional hwpmc
>>  dev/hwpmc/hwpmc_mod.c          optional hwpmc
>> +dev/hwpmc/hwpmc_soft.c         optional hwpmc
>>  dev/ichsmb/ichsmb.c            optional ichsmb
>>  dev/ichsmb/ichsmb_pci.c                optional ichsmb pci
>>  dev/ida/ida.c                  optional ida
>>
>> Modified: head/sys/dev/hwpmc/hwpmc_amd.c
>> ==============================================================================
>> --- head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -687,7 +687,8 @@ amd_intr(int cpu, struct trapframe *tf)
>>                wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
>>
>>                /* Restart the counter if logging succeeded. */
>> -               error = pmc_process_interrupt(cpu, pm, tf, TRAPF_USERMODE(tf));
>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>> +                   TRAPF_USERMODE(tf));
>>                if (error == 0)
>>                        wrmsr(evsel, config | AMD_PMC_ENABLE);
>>        }
>> @@ -874,7 +875,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int c
>>  struct pmc_mdep *
>>  pmc_amd_initialize(void)
>>  {
>> -       int classindex, error, i, nclasses, ncpus;
>> +       int classindex, error, i, ncpus;
>>        struct pmc_classdep *pcd;
>>        enum pmc_cputype cputype;
>>        struct pmc_mdep *pmc_mdep;
>> @@ -926,12 +927,9 @@ pmc_amd_initialize(void)
>>         * These processors have two classes of PMCs: the TSC and
>>         * programmable PMCs.
>>         */
>> -       nclasses = 2;
>> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses * sizeof (struct pmc_classdep),
>> -           M_PMC, M_WAITOK|M_ZERO);
>> +       pmc_mdep = pmc_mdep_alloc(2);
>>
>>        pmc_mdep->pmd_cputype = cputype;
>> -       pmc_mdep->pmd_nclass  = nclasses;
>>
>>        ncpus = pmc_cpu_max();
>>
>>
>> Modified: head/sys/dev/hwpmc/hwpmc_core.c
>> ==============================================================================
>> --- head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -2239,7 +2239,7 @@ core_intr(int cpu, struct trapframe *tf)
>>                if (pm->pm_state != PMC_STATE_RUNNING)
>>                        continue;
>>
>> -               error = pmc_process_interrupt(cpu, pm, tf,
>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>                    TRAPF_USERMODE(tf));
>>
>>                v = pm->pm_sc.pm_reloadcount;
>> @@ -2326,7 +2326,7 @@ core2_intr(int cpu, struct trapframe *tf
>>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>>                        continue;
>>
>> -               error = pmc_process_interrupt(cpu, pm, tf,
>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>                    TRAPF_USERMODE(tf));
>>                if (error)
>>                        intrenable &= ~flag;
>> @@ -2354,7 +2354,7 @@ core2_intr(int cpu, struct trapframe *tf
>>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>>                        continue;
>>
>> -               error = pmc_process_interrupt(cpu, pm, tf,
>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>                    TRAPF_USERMODE(tf));
>>                if (error)
>>                        intrenable &= ~flag;
>>
>> Modified: head/sys/dev/hwpmc/hwpmc_intel.c
>> ==============================================================================
>> --- head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -162,12 +162,10 @@ pmc_intel_initialize(void)
>>                return (NULL);
>>        }
>>
>> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses *
>> -           sizeof(struct pmc_classdep), M_PMC, M_WAITOK|M_ZERO);
>> +       /* Allocate base class and initialize machine dependent struct */
>> +       pmc_mdep = pmc_mdep_alloc(nclasses);
>>
>>        pmc_mdep->pmd_cputype    = cputype;
>> -       pmc_mdep->pmd_nclass     = nclasses;
>> -
>>        pmc_mdep->pmd_switch_in  = intel_switch_in;
>>        pmc_mdep->pmd_switch_out = intel_switch_out;
>>
>>
>> Modified: head/sys/dev/hwpmc/hwpmc_logging.c
>> ==============================================================================
>> --- head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -129,6 +129,7 @@ static struct mtx pmc_kthread_mtx;  /* sl
>>
>>  /* Emit a string.  Caution: does NOT update _le, so needs to be last */
>>  #define        PMCLOG_EMITSTRING(S,L)  do { bcopy((S), _le, (L)); } while (0)
>> +#define        PMCLOG_EMITNULLSTRING(L) do { bzero(_le, (L)); } while (0)
>>
>>  #define        PMCLOG_DESPATCH(PO)                                             \
>>                pmclog_release((PO));                                   \
>> @@ -835,16 +836,33 @@ void
>>  pmclog_process_pmcallocate(struct pmc *pm)
>>  {
>>        struct pmc_owner *po;
>> +       struct pmc_soft *ps;
>>
>>        po = pm->pm_owner;
>>
>>        PMCDBG(LOG,ALL,1, "pm=%p", pm);
>>
>> -       PMCLOG_RESERVE(po, PMCALLOCATE, sizeof(struct pmclog_pmcallocate));
>> -       PMCLOG_EMIT32(pm->pm_id);
>> -       PMCLOG_EMIT32(pm->pm_event);
>> -       PMCLOG_EMIT32(pm->pm_flags);
>> -       PMCLOG_DESPATCH(po);
>> +       if (PMC_TO_CLASS(pm) == PMC_CLASS_SOFT) {
>> +               PMCLOG_RESERVE(po, PMCALLOCATEDYN,
>> +                   sizeof(struct pmclog_pmcallocatedyn));
>> +               PMCLOG_EMIT32(pm->pm_id);
>> +               PMCLOG_EMIT32(pm->pm_event);
>> +               PMCLOG_EMIT32(pm->pm_flags);
>> +               ps = pmc_soft_ev_acquire(pm->pm_event);
>> +               if (ps != NULL)
>> +                       PMCLOG_EMITSTRING(ps->ps_ev.pm_ev_name,PMC_NAME_MAX);
>> +               else
>> +                       PMCLOG_EMITNULLSTRING(PMC_NAME_MAX);
>> +               pmc_soft_ev_release(ps);
>> +               PMCLOG_DESPATCH(po);
>> +       } else {
>> +               PMCLOG_RESERVE(po, PMCALLOCATE,
>> +                   sizeof(struct pmclog_pmcallocate));
>> +               PMCLOG_EMIT32(pm->pm_id);
>> +               PMCLOG_EMIT32(pm->pm_event);
>> +               PMCLOG_EMIT32(pm->pm_flags);
>> +               PMCLOG_DESPATCH(po);
>> +       }
>>  }
>>
>>  void
>>
>> Modified: head/sys/dev/hwpmc/hwpmc_mips.c
>> ==============================================================================
>> --- head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -287,7 +287,7 @@ mips_pmc_intr(int cpu, struct trapframe
>>                retval = 1;
>>                if (pm->pm_state != PMC_STATE_RUNNING)
>>                        continue;
>> -               error = pmc_process_interrupt(cpu, pm, tf,
>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>                    TRAPF_USERMODE(tf));
>>                if (error) {
>>                        /* Clear/disable the relevant counter */
>>
>> Modified: head/sys/dev/hwpmc/hwpmc_mod.c
>> ==============================================================================
>> --- head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:49:11 2012        (r233627)
>> +++ head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:58:30 2012        (r233628)
>> @@ -70,6 +70,8 @@ __FBSDID("$FreeBSD$");
>>  #include <vm/vm_map.h>
>>  #include <vm/vm_object.h>
>>
>> +#include "hwpmc_soft.h"
>> +
>>  /*
>>  * Types
>>  */
>> @@ -182,7 +184,7 @@ static int  pmc_attach_one_process(struct
>>  static int     pmc_can_allocate_rowindex(struct proc *p, unsigned int ri,
>>     int cpu);
>>  static int     pmc_can_attach(struct pmc *pm, struct proc *p);
>> -static void    pmc_capture_user_callchain(int cpu, struct trapframe *tf);
>> +static void    pmc_capture_user_callchain(int cpu, int soft, struct trapframe *tf);
>>  static void    pmc_cleanup(void);
>>  static int     pmc_detach_process(struct proc *p, struct pmc *pm);
>>  static int     pmc_detach_one_process(struct proc *p, struct pmc *pm,
>> @@ -206,7 +208,7 @@ static void pmc_process_csw_out(struct t
>>  static void    pmc_process_exit(void *arg, struct proc *p);
>>  static void    pmc_process_fork(void *arg, struct proc *p1,
>>     struct proc *p2, int n);
>> -static void    pmc_process_samples(int cpu);
>> +static void    pmc_process_samples(int cpu, int soft);
>>  static void    pmc_release_pmc_descriptor(struct pmc *pmc);
>>  static void    pmc_remove_owner(struct pmc_owner *po);
>>  static void    pmc_remove_process_descriptor(struct pmc_process *pp);
>> @@ -218,12 +220,16 @@ static int        pmc_stop(struct pmc *pm);
>>  static int     pmc_syscall_handler(struct thread *td, void *syscall_args);
>>  static void    pmc_unlink_target_process(struct pmc *pmc,
>>     struct pmc_process *pp);
>> +static int generic_switch_in(struct pmc_cpu *pc, struct pmc_process *pp);
>> +static int generic_switch_out(struct pmc_cpu *pc, struct pmc_process *pp);
>> +static struct pmc_mdep *pmc_generic_cpu_initialize(void);
>> +static void pmc_generic_cpu_finalize(struct pmc_mdep *md);
>>
>>  /*
>>  * Kernel tunables and sysctl(8) interface.
>>  */
>>
>> -SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0, "HWPMC parameters");
>> +SYSCTL_DECL(_kern_hwpmc);
>>
>>  static int pmc_callchaindepth = PMC_CALLCHAIN_DEPTH;
>>  TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "callchaindepth", &pmc_callchaindepth);
>> @@ -1833,7 +1839,9 @@ const char *pmc_hooknames[] = {
>>        "KLDUNLOAD",
>>        "MMAP",
>>        "MUNMAP",
>> -       "CALLCHAIN"
>> +       "CALLCHAIN-NMI",
>> +       "CALLCHAIN-SOFT",
>> +       "SOFTSAMPLING"
>>  };
>>  #endif
>>
>> @@ -1992,7 +2000,8 @@ pmc_hook_handler(struct thread *td, int
>>                 * lose the interrupt sample.
>>                 */
>>                CPU_CLR_ATOMIC(PCPU_GET(cpuid), &pmc_cpumask);
>> -               pmc_process_samples(PCPU_GET(cpuid));
>> +               pmc_process_samples(PCPU_GET(cpuid), PMC_HR);
>> +               pmc_process_samples(PCPU_GET(cpuid), PMC_SR);
>>                break;
>>
>>
>> @@ -2022,11 +2031,30 @@ pmc_hook_handler(struct thread *td, int
>>                 */
>>                KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>>                    __LINE__));
>> -               pmc_capture_user_callchain(PCPU_GET(cpuid),
>> +
>> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_HR,
>>                    (struct trapframe *) arg);
>>                td->td_pflags &= ~TDP_CALLCHAIN;
>>                break;
>>
>> +       case PMC_FN_USER_CALLCHAIN_SOFT:
>> +               /*
>> +                * Record a call chain.
>> +                */
>> +               KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>> +                   __LINE__));
>> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_SR,
>> +                   (struct trapframe *) arg);
>> +               td->td_pflags &= ~TDP_CALLCHAIN;
>> +               break;
>> +
>> +       case PMC_FN_SOFT_SAMPLING:
>> +               /*
>> +                * Call soft PMC sampling intr.
>> +                */
>> +               pmc_soft_intr((struct pmckern_soft *) arg);
>> +               break;
>> +
>>        default:
>>  #ifdef DEBUG
>>                KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
>> @@ -2221,18 +2249,17 @@ pmc_destroy_pmc_descriptor(struct pmc *p
>>  static void
>>  pmc_wait_for_pmc_idle(struct pmc *pm)
>>  {
>> -#ifdef DEBUG
>> +#ifdef DEBUG
>>        volatile int maxloop;
>>
>>        maxloop = 100 * pmc_cpu_max();
>>  #endif
>> -
>>        /*
>>         * Loop (with a forced context switch) till the PMC's runcount
>>         * comes down to zero.
>>         */
>>        while (atomic_load_acq_32(&pm->pm_runcount) > 0) {
>> -#ifdef DEBUG
>> +#ifdef DEBUG
>>                maxloop--;
>>                KASSERT(maxloop > 0,
>>                    ("[pmc,%d] (ri%d, rc%d) waiting too long for "
>> @@ -2972,6 +2999,53 @@ pmc_syscall_handler(struct thread *td, v
>>        }
>>        break;
>>
>> +       /*
>> +        * Retrieve soft events list.
>> +        */
>> +       case PMC_OP_GETDYNEVENTINFO:
>> +       {
>> +               enum pmc_class                  cl;
>> +               enum pmc_event                  ev;
>> +               struct pmc_op_getdyneventinfo   *gei;
>> +               struct pmc_dyn_event_descr      dev;
>> +               struct pmc_soft                 *ps;
>> +               uint32_t                        nevent;
>> +
>> +               sx_assert(&pmc_sx, SX_LOCKED);
>> +
>> +               gei = (struct pmc_op_getdyneventinfo *) arg;
>> +
>> +               if ((error = copyin(&gei->pm_class, &cl, sizeof(cl))) != 0)
>> +                       break;
>> +
>> +               /* Only SOFT class is dynamic. */
>> +               if (cl != PMC_CLASS_SOFT) {
>> +                       error = EINVAL;
>> +                       break;
>> +               }
>> +
>> +               nevent = 0;
>> +               for (ev = PMC_EV_SOFT_FIRST; ev <= PMC_EV_SOFT_LAST; ev++) {
>> +                       ps = pmc_soft_ev_acquire(ev);
>> +                       if (ps == NULL)
>> +                               continue;
>> +                       bcopy(&ps->ps_ev, &dev, sizeof(dev));
>> +                       pmc_soft_ev_release(ps);
>> +
>> +                       error = copyout(&dev,
>> +                           &gei->pm_events[nevent],
>> +                           sizeof(struct pmc_dyn_event_descr));
>> +                       if (error != 0)
>> +                               break;
>> +                       nevent++;
>> +               }
>> +               if (error != 0)
>> +                       break;
>> +
>> +               error = copyout(&nevent, &gei->pm_nevent,
>>
>> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


--
Monthadar Al Jaberi

_______________________________________________
[hidden email] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-mips
To unsubscribe, send any mail to "[hidden email]"

RSPRO_USB_PROD (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: svn commit: r233628 - in head: lib/libpmc sys/amd64/amd64 sys/amd64/include sys/arm/include sys/conf sys/dev/hwpmc sys/i386/i386 sys/i386/include sys/kern sys/mips/include sys/modules/hwpmc sys/pow...

Fabien THOMAS
Hi,

The rumors seems true :)
Can you try the patch attached (I cannot test as i've no MIPS hardware) ?

Thanks,
Fabien


> On Mon, Apr 23, 2012 at 8:44 AM, Adrian Chadd <[hidden email]> wrote:
>> Hi Fabien,
>>
>> I've heard some rumours that this broke hwpmc support for mips24k.
>>
>> Monthadar, can you please provide some background info for this?
>>
>
> This is the log output
>
> Using default protocol (TFTP)
> Entry point: 0x80050100, address range: 0x80050000-0x804f1dcc
> RedBoot> exec
> Now booting linux kernel:
> Base address 0x80050000 Entry 0x80050100
> memsize=0x08000000
> modetty0=0,n,8,1,hw
> board=RouterStation PRO
> ethaddr=00.15.6d.c8.c9.2e
> CPU platform: Atheros AR7161 rev 2
> CPU Frequency=720 MHz
> CPU DDR Frequency=360 MHz
> CPU AHB Frequency=180 MHz
> platform frequency: 720000000
> arguments:
>  a0 = 00000002
>  a1 = 80050028
>  a2 = 80050000
>  a3 = 00000001
> Cmd line:  �������m���������������_}������߾q��������������������������������߿���������_�w���������?-����{������~��
> Environment:
>  memsize = 0x08000000
>  modetty0 = 0,n,8,1,hw
>  ethaddr = 00.15.6d.c8.c9.2e
>  board = RouterStation PRO
> Cache info:
>  picache_stride    = 4096
>  picache_loopcount = 16
>  pdcache_stride    = 4096
>  pdcache_loopcount = 8
> cpu0: MIPS Technologies processor v116.147
>  MMU: Standard TLB, 16 entries
>  L1 i-cache: 4 ways of 512 sets, 32 bytes per line
>  L1 d-cache: 4 ways of 256 sets, 32 bytes per line
>  Config1=0x9ee3519e<PerfCount,WatchRegs,MIPS16,EJTAG>
>  Config3=0x20
> KDB: debugger backends: ddb
> KDB: current backend: ddb
> Copyright (c) 1992-2012 The FreeBSD Project.
> Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
> The Regents of the University of California. All rights reserved.
> FreeBSD is a registered trademark of The FreeBSD Foundation.
> FreeBSD 10.0-CURRENT #12: Fri Apr 20 18:03:16 CEST 2012
>    root@freebsd-re-9:/usr/obj/mips.mips/usr/src/sys/RSPRO_USB_PROD mips
> WARNING: WITNESS option enabled, expect reduced performance.
> MEMGUARD DEBUGGING ALLOCATOR INITIALIZED:
> MEMGUARD map base: 0xc0800000
> MEMGUARD map limit: 0xc1c00000
> MEMGUARD map size: 20480 KBytes
> real memory  = 134217728 (131072K bytes)
> avail memory = 123117568 (117MB)
> random device not loaded; using insecure entropy
> nexus0: <MIPS32 root nexus>
> clock0: <Generic MIPS32 ticker> on nexus0
> Timecounter "MIPS32" frequency 360000000 Hz quality 800
> Event timer "MIPS32" frequency 360000000 Hz quality 800
> apb0 at irq 4 on nexus0
> uart0: <16550 or compatible> on apb0
> uart0: console (115200,n,8,1)
> gpio0: <Atheros AR71XX GPIO driver> on apb0
> gpio0: [GIANT-LOCKED]
> gpio0: gpio pinmask=0x0
> gpioc0: <GPIO controller> on gpio0
> gpiobus0: <GPIO bus> on gpio0
> ehci0: <AR71XX Integrated USB 2.0 controller> at mem
> 0x1b000000-0x1bffffff irq 1 on nexus0
> usbus0: set host controller mode
> usbus0: EHCI version 1.0
> usbus0: set host controller mode
> usbus0 on ehci0
> pcib0 at irq 0 on nexus0
> pci0: <PCI bus> on pcib0
> pci0: <old, non-VGA display device> at device 0.0 (no driver attached)
> ath0: <Atheros 5413> irq 0 at device 17.0 on pci0
> ath0: AR5413 mac 10.5 RF5413 phy 6.1
> ath0: 2GHz radio: 0x0000; 5GHz radio: 0x0063
> arge0: <Atheros AR71xx built-in ethernet interface> at mem
> 0x19000000-0x19000fff irq 2 on nexus0
> arge0: No PHY specified, using mask 16
> miibus0: <MII bus> on arge0
> ukphy0: <Generic IEEE 802.3u media interface> PHY 4 on miibus0
> ukphy0:  none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX,
> 1000baseT-FDX, 1000baseT-FDX-master, auto
> arge0: Ethernet address: 00:15:6d:c8:c9:2e
> arge1: <Atheros AR71xx built-in ethernet interface> at mem
> 0x1a000000-0x1a000fff irq 3 on nexus0
> arge1: No PHY specified, using mask 15
> arge1: Ethernet address: 00:15:6d:c8:c9:2f
> spi0: <AR71XX SPI> at mem 0x1f000000-0x1f00000f on nexus0
> spibus0: <spibus bus> on spi0
> mx25l0: <M25Pxx Flash Family> at cs 0 on spibus0
> mx25l0: mx25ll128, sector 65536 bytes, 256 sectors
> ar71xx_wdog0: <Atheros AR71XX watchdog timer> on nexus0
> Timecounters tick every 1.000 msec
> usbus0: 480Mbps High Speed USB v2.0
> ugen0.1: <Atheros> at usbus0
> uhub0: <Atheros EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus0
> panic: [pmc,4816] npmc miscomputed: ri=0, md->npmc=2
> KDB: enter: panic
> [ thread pid 0 tid 100000 ]
> Stopped at      kdb_enter+0x4c: lui     at,0x8050
> db> tr
> Tracing pid 0 tid 100000 td 0x804f76d0
> db_trace_thread+30 (?,?,?,?) ra 8068b94800000018 sp 0 sz 0
> 80075adc+114 (0,?,ffffffff,?) ra 8068b96000000020 sp 100000000 sz 1
> 80074e24+388 (?,?,?,?) ra 8068b980000000a8 sp 0 sz 0
> db_command_loop+70 (?,?,?,?) ra 8068ba2800000018 sp 0 sz 0
> 80077900+f4 (?,?,?,?) ra 8068ba40000001a8 sp 0 sz 0
> kdb_trap+110 (?,?,?,?) ra 8068bbe800000030 sp 0 sz 0
> trap+c7c (?,?,?,?) ra 8068bc18000000b8 sp 0 sz 0
> MipsKernGenException+134 (0,4,8043b1d4,119) ra 8068bcd0000000c8 sp
> 100000001 sz 1
> kdb_enter+4c (?,?,?,?) ra 8068bd9800000018 sp 0 sz 0
> panic+11c (?,12d0,0,2) ra 8068bdb000000028 sp 1 sz 1
> 800e8ca8+274 (?,?,?,?) ra 8068bdd800000038 sp 0 sz 0
> syscall_module_handler+b8 (?,?,?,?) ra 8068be1000000028 sp 0 sz 0
> module_register_init+9c (?,?,?,?) ra 8068be3800000028 sp 0 sz 0
> mi_startup+138 (?,?,?,?) ra 8068be6000000020 sp 0 sz 0
> _start+90 (?,?,?,?) ra 8068be8000000000 sp 0 sz 0
> pid 0
> db>
>
>> Thanks,
>>
>>
>>
>> adrian
>>
>> On 28 March 2012 13:58, Fabien Thomas <[hidden email]> wrote:
>>> Author: fabient
>>> Date: Wed Mar 28 20:58:30 2012
>>> New Revision: 233628
>>> URL: http://svn.freebsd.org/changeset/base/233628
>>>
>>> Log:
>>>  Add software PMC support.
>>>
>>>  New kernel events can be added at various location for sampling or counting.
>>>  This will for example allow easy system profiling whatever the processor is
>>>  with known tools like pmcstat(8).
>>>
>>>  Simultaneous usage of software PMC and hardware PMC is possible, for example
>>>  looking at the lock acquire failure, page fault while sampling on
>>>  instructions.
>>>
>>>  Sponsored by: NETASQ
>>>  MFC after:    1 month
>>>
>>> Added:
>>>  head/lib/libpmc/pmc.soft.3   (contents, props changed)
>>>  head/sys/dev/hwpmc/hwpmc_soft.c   (contents, props changed)
>>>  head/sys/dev/hwpmc/hwpmc_soft.h   (contents, props changed)
>>> Modified:
>>>  head/lib/libpmc/Makefile
>>>  head/lib/libpmc/libpmc.c
>>>  head/lib/libpmc/pmc.3
>>>  head/lib/libpmc/pmc.atom.3
>>>  head/lib/libpmc/pmc.core.3
>>>  head/lib/libpmc/pmc.core2.3
>>>  head/lib/libpmc/pmc.corei7.3
>>>  head/lib/libpmc/pmc.corei7uc.3
>>>  head/lib/libpmc/pmc.iaf.3
>>>  head/lib/libpmc/pmc.k7.3
>>>  head/lib/libpmc/pmc.k8.3
>>>  head/lib/libpmc/pmc.mips24k.3
>>>  head/lib/libpmc/pmc.octeon.3
>>>  head/lib/libpmc/pmc.p4.3
>>>  head/lib/libpmc/pmc.p5.3
>>>  head/lib/libpmc/pmc.p6.3
>>>  head/lib/libpmc/pmc.sandybridge.3
>>>  head/lib/libpmc/pmc.sandybridgeuc.3
>>>  head/lib/libpmc/pmc.tsc.3
>>>  head/lib/libpmc/pmc.ucf.3
>>>  head/lib/libpmc/pmc.westmere.3
>>>  head/lib/libpmc/pmc.westmereuc.3
>>>  head/lib/libpmc/pmc.xscale.3
>>>  head/lib/libpmc/pmclog.c
>>>  head/lib/libpmc/pmclog.h
>>>  head/sys/amd64/amd64/trap.c
>>>  head/sys/amd64/include/pmc_mdep.h
>>>  head/sys/arm/include/pmc_mdep.h
>>>  head/sys/conf/files
>>>  head/sys/dev/hwpmc/hwpmc_amd.c
>>>  head/sys/dev/hwpmc/hwpmc_core.c
>>>  head/sys/dev/hwpmc/hwpmc_intel.c
>>>  head/sys/dev/hwpmc/hwpmc_logging.c
>>>  head/sys/dev/hwpmc/hwpmc_mips.c
>>>  head/sys/dev/hwpmc/hwpmc_mod.c
>>>  head/sys/dev/hwpmc/hwpmc_piv.c
>>>  head/sys/dev/hwpmc/hwpmc_powerpc.c
>>>  head/sys/dev/hwpmc/hwpmc_ppro.c
>>>  head/sys/dev/hwpmc/hwpmc_tsc.c
>>>  head/sys/dev/hwpmc/hwpmc_x86.c
>>>  head/sys/dev/hwpmc/hwpmc_xscale.c
>>>  head/sys/dev/hwpmc/pmc_events.h
>>>  head/sys/i386/i386/trap.c
>>>  head/sys/i386/include/pmc_mdep.h
>>>  head/sys/kern/kern_clock.c
>>>  head/sys/kern/kern_lock.c
>>>  head/sys/kern/kern_mutex.c
>>>  head/sys/kern/kern_pmc.c
>>>  head/sys/kern/kern_rwlock.c
>>>  head/sys/kern/kern_sx.c
>>>  head/sys/kern/subr_trap.c
>>>  head/sys/mips/include/pmc_mdep.h
>>>  head/sys/modules/hwpmc/Makefile
>>>  head/sys/powerpc/include/pmc_mdep.h
>>>  head/sys/sys/pmc.h
>>>  head/sys/sys/pmckern.h
>>>  head/sys/sys/pmclog.h
>>>  head/usr.sbin/pmcstat/pmcstat_log.c
>>>
>>> Modified: head/lib/libpmc/Makefile
>>> ==============================================================================
>>> --- head/lib/libpmc/Makefile    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/Makefile    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -20,6 +20,7 @@ MAN+= pmc_read.3
>>>  MAN+=  pmc_set.3
>>>  MAN+=  pmc_start.3
>>>  MAN+=  pmclog.3
>>> +MAN+=  pmc.soft.3
>>>
>>>  # PMC-dependent manual pages
>>>  .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
>>>
>>> Modified: head/lib/libpmc/libpmc.c
>>> ==============================================================================
>>> --- head/lib/libpmc/libpmc.c    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/libpmc.c    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -77,11 +77,12 @@ static int tsc_allocate_pmc(enum pmc_eve
>>>  static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>>>     struct pmc_op_pmcallocate *_pmc_config);
>>>  #endif
>>> -
>>>  #if defined(__mips__)
>>>  static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>>>                             struct pmc_op_pmcallocate *_pmc_config);
>>>  #endif /* __mips__ */
>>> +static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>>> +    struct pmc_op_pmcallocate *_pmc_config);
>>>
>>>  #if defined(__powerpc__)
>>>  static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>>> @@ -156,6 +157,8 @@ PMC_CLASSDEP_TABLE(octeon, OCTEON);
>>>  PMC_CLASSDEP_TABLE(ucf, UCF);
>>>  PMC_CLASSDEP_TABLE(ppc7450, PPC7450);
>>>
>>> +static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT];
>>> +
>>>  #undef __PMC_EV_ALIAS
>>>  #define        __PMC_EV_ALIAS(N,CODE)  { N, PMC_EV_##CODE },
>>>
>>> @@ -215,21 +218,22 @@ static const struct pmc_event_descr west
>>>                PMC_CLASS_##C, __VA_ARGS__                      \
>>>        }
>>>
>>> -PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>> -PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
>>> -PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>> -PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>> -PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>> -PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>> -PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
>>> -PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
>>> -PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
>>> -PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC);
>>> -PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC);
>>> -PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE);
>>> -PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K);
>>> -PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_OCTEON);
>>> -PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_PPC7450);
>>> +PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>> +PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>> +PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>> +PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>> +PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>> +PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>> +PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>> +PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>> +PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>> +PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>> +PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>> +PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE);
>>> +PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K);
>>> +PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON);
>>> +PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450);
>>> +PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT);
>>>
>>>  static const struct pmc_event_descr tsc_event_table[] =
>>>  {
>>> @@ -279,16 +283,24 @@ PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc)
>>>  #if    defined(__XSCALE__)
>>>  PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale);
>>>  #endif
>>> -
>>>  #if defined(__mips__)
>>>  PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips);
>>>  PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips);
>>>  #endif /* __mips__ */
>>> -
>>>  #if defined(__powerpc__)
>>>  PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450);
>>>  #endif
>>>
>>> +static struct pmc_class_descr soft_class_table_descr =
>>> +{
>>> +       .pm_evc_name  = "SOFT-",
>>> +       .pm_evc_name_size = sizeof("SOFT-") - 1,
>>> +       .pm_evc_class = PMC_CLASS_SOFT,
>>> +       .pm_evc_event_table = NULL,
>>> +       .pm_evc_event_table_size = 0,
>>> +       .pm_evc_allocate_pmc = soft_allocate_pmc
>>> +};
>>> +
>>>  #undef PMC_CLASS_TABLE_DESC
>>>
>>>  static const struct pmc_class_descr **pmc_class_table;
>>> @@ -343,9 +355,12 @@ static const char * pmc_state_names[] =
>>>        __PMC_STATES()
>>>  };
>>>
>>> -static int pmc_syscall = -1;           /* filled in by pmc_init() */
>>> -
>>> -static struct pmc_cpuinfo cpu_info;    /* filled in by pmc_init() */
>>> +/*
>>> + * Filled in by pmc_init().
>>> + */
>>> +static int pmc_syscall = -1;
>>> +static struct pmc_cpuinfo cpu_info;
>>> +static struct pmc_op_getdyneventinfo soft_event_info;
>>>
>>>  /* Event masks for events */
>>>  struct pmc_masks {
>>> @@ -2179,6 +2194,25 @@ tsc_allocate_pmc(enum pmc_event pe, char
>>>  }
>>>  #endif
>>>
>>> +static struct pmc_event_alias generic_aliases[] = {
>>> +       EV_ALIAS("instructions",                "SOFT-CLOCK.HARD"),
>>> +       EV_ALIAS(NULL, NULL)
>>> +};
>>> +
>>> +static int
>>> +soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
>>> +    struct pmc_op_pmcallocate *pmc_config)
>>> +{
>>> +       (void)ctrspec;
>>> +       (void)pmc_config;
>>> +
>>> +       if (pe < PMC_EV_SOFT_FIRST || pe > PMC_EV_SOFT_LAST)
>>> +               return (-1);
>>> +
>>> +       pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
>>> +       return (0);
>>> +}
>>> +
>>>  #if    defined(__XSCALE__)
>>>
>>>  static struct pmc_event_alias xscale_aliases[] = {
>>> @@ -2663,6 +2697,10 @@ pmc_event_names_of_class(enum pmc_class
>>>                ev = ppc7450_event_table;
>>>                count = PMC_EVENT_TABLE_SIZE(ppc7450);
>>>                break;
>>> +       case PMC_CLASS_SOFT:
>>> +               ev = soft_event_table;
>>> +               count = soft_event_info.pm_nevent;
>>> +               break;
>>>        default:
>>>                errno = EINVAL;
>>>                return (-1);
>>> @@ -2676,6 +2714,7 @@ pmc_event_names_of_class(enum pmc_class
>>>
>>>        for (;count--; ev++, names++)
>>>                *names = ev->pm_ev_name;
>>> +
>>>        return (0);
>>>  }
>>>
>>> @@ -2780,11 +2819,34 @@ pmc_init(void)
>>>                pmc_class_table[n] = NULL;
>>>
>>>        /*
>>> +        * Get soft events list.
>>> +        */
>>> +       soft_event_info.pm_class = PMC_CLASS_SOFT;
>>> +       if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0)
>>> +               return (pmc_syscall = -1);
>>> +
>>> +       /* Map soft events to static list. */
>>> +       for (n = 0; n < soft_event_info.pm_nevent; n++) {
>>> +               soft_event_table[n].pm_ev_name =
>>> +                   soft_event_info.pm_events[n].pm_ev_name;
>>> +               soft_event_table[n].pm_ev_code =
>>> +                   soft_event_info.pm_events[n].pm_ev_code;
>>> +       }
>>> +       soft_class_table_descr.pm_evc_event_table_size = \
>>> +           soft_event_info.pm_nevent;
>>> +       soft_class_table_descr.pm_evc_event_table = \
>>> +           soft_event_table;
>>> +
>>> +       /*
>>>         * Fill in the class table.
>>>         */
>>>        n = 0;
>>> +
>>> +       /* Fill soft events information. */
>>> +       pmc_class_table[n++] = &soft_class_table_descr;
>>>  #if defined(__amd64__) || defined(__i386__)
>>> -       pmc_class_table[n++] = &tsc_class_table_descr;
>>> +       if (cpu_info.pm_cputype != PMC_CPU_GENERIC)
>>> +               pmc_class_table[n++] = &tsc_class_table_descr;
>>>
>>>        /*
>>>         * Check if this CPU has fixed function counters.
>>> @@ -2867,6 +2929,9 @@ pmc_init(void)
>>>                pmc_class_table[n] = &p4_class_table_descr;
>>>                break;
>>>  #endif
>>> +       case PMC_CPU_GENERIC:
>>> +               PMC_MDEP_INIT(generic);
>>> +               break;
>>>  #if defined(__XSCALE__)
>>>        case PMC_CPU_INTEL_XSCALE:
>>>                PMC_MDEP_INIT(xscale);
>>> @@ -3035,18 +3100,19 @@ _pmc_name_of_event(enum pmc_event pe, en
>>>                evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale);
>>>        } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) {
>>>                ev = mips24k_event_table;
>>> -               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k
>>> -);
>>> +               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k);
>>>        } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) {
>>>                ev = octeon_event_table;
>>>                evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon);
>>>        } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) {
>>>                ev = ppc7450_event_table;
>>> -               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450
>>> -);
>>> +               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450);
>>>        } else if (pe == PMC_EV_TSC_TSC) {
>>>                ev = tsc_event_table;
>>>                evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
>>> +       } else if (pe >= PMC_EV_SOFT_FIRST && pe <= PMC_EV_SOFT_LAST) {
>>> +               ev = soft_event_table;
>>> +               evfence = soft_event_table + soft_event_info.pm_nevent;
>>>        }
>>>
>>>        for (; ev != evfence; ev++)
>>>
>>> Modified: head/lib/libpmc/pmc.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.3       Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.3       Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -223,6 +223,8 @@ and
>>>  CPUs.
>>>  .It Li PMC_CLASS_TSC
>>>  The timestamp counter on i386 and amd64 architecture CPUs.
>>> +.It Li PMC_CLASS_SOFT
>>> +Software events.
>>>  .El
>>>  .Ss PMC Capabilities
>>>  Capabilities of performance monitoring hardware are denoted using
>>> @@ -525,6 +527,7 @@ API is
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmclog 3 ,
>>>  .Xr hwpmc 4 ,
>>>
>>> Modified: head/lib/libpmc/pmc.atom.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -1176,6 +1176,7 @@ and the underlying hardware events used
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.core.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.core.3  Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.core.3  Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -792,6 +792,7 @@ may not count some transitions.
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmclog 3 ,
>>>  .Xr hwpmc 4
>>>
>>> Modified: head/lib/libpmc/pmc.core2.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -1107,6 +1107,7 @@ and the underlying hardware events used.
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.corei7.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -1559,6 +1559,7 @@ Counts number of segment register loads.
>>>  .Xr pmc.corei7uc 3 ,
>>>  .Xr pmc.westmere 3 ,
>>>  .Xr pmc.westmereuc 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.corei7uc.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -863,6 +863,7 @@ refreshed or needs to go into a power do
>>>  .Xr pmc.corei7 3 ,
>>>  .Xr pmc.westmere 3 ,
>>>  .Xr pmc.westmereuc 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.iaf.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -132,6 +132,7 @@ CPU, use the event specifier
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.k7.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -249,6 +249,7 @@ and the underlying hardware events used.
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmclog 3 ,
>>>  .Xr hwpmc 4
>>>
>>> Modified: head/lib/libpmc/pmc.k8.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -783,6 +783,7 @@ and the underlying hardware events used.
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmclog 3 ,
>>>  .Xr hwpmc 4
>>>
>>> Modified: head/lib/libpmc/pmc.mips24k.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -392,6 +392,7 @@ and the underlying hardware events used.
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.octeon.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -232,6 +232,7 @@ and the underlying hardware events used.
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.p4.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -1208,6 +1208,7 @@ and the underlying hardware events used.
>>>  .Xr pmc.k8 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmclog 3 ,
>>>  .Xr hwpmc 4
>>>
>>> Modified: head/lib/libpmc/pmc.p5.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -444,6 +444,7 @@ and the underlying hardware events used.
>>>  .Xr pmc.k8 3 ,
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmclog 3 ,
>>>  .Xr hwpmc 4
>>>
>>> Modified: head/lib/libpmc/pmc.p6.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -1010,6 +1010,7 @@ and the underlying hardware events used.
>>>  .Xr pmc.k8 3 ,
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmclog 3 ,
>>>  .Xr hwpmc 4
>>>
>>> Modified: head/lib/libpmc/pmc.sandybridge.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -907,6 +907,7 @@ Split locks in SQ.
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>>  .Xr pmc.sandybridgeuc 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc.ucf 3 ,
>>>  .Xr pmc.westmere 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.sandybridgeuc.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -208,6 +208,7 @@ Counts the number of core-outgoing entri
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>>  .Xr pmc.sandybridge 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc.ucf 3 ,
>>>  .Xr pmc.westmere 3 ,
>>>
>>> Added: head/lib/libpmc/pmc.soft.3
>>> ==============================================================================
>>> --- /dev/null   00:00:00 1970   (empty, because file is newly added)
>>> +++ head/lib/libpmc/pmc.soft.3  Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -0,0 +1,104 @@
>>> +.\" Copyright (c) 2012 Fabien Thomas.  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$
>>> +.\"
>>> +.Dd March 28, 2012
>>> +.Os
>>> +.Dt PMC.SOFT 3
>>> +.Sh NAME
>>> +.Nm pmc.soft
>>> +.Nd measurements using software based events
>>> +.Sh LIBRARY
>>> +.Lb libpmc
>>> +.Sh SYNOPSIS
>>> +.In pmc.h
>>> +.Sh DESCRIPTION
>>> +Software events are used to collect various source of software events.
>>> +.Ss PMC Features
>>> +16 sampling counters using software events based on various sources.
>>> +These PMCs support the following capabilities:
>>> +.Bl -column "PMC_CAP_INTERRUPT" "Support"
>>> +.It Em Capability Ta Em Support
>>> +.It PMC_CAP_CASCADE Ta \&No
>>> +.It PMC_CAP_EDGE Ta \&No
>>> +.It PMC_CAP_INTERRUPT Ta Yes
>>> +.It PMC_CAP_INVERT Ta \&No
>>> +.It PMC_CAP_READ Ta Yes
>>> +.It PMC_CAP_PRECISE Ta \&No
>>> +.It PMC_CAP_SYSTEM Ta Yes
>>> +.It PMC_CAP_TAGGING Ta \&No
>>> +.It PMC_CAP_THRESHOLD Ta \&No
>>> +.It PMC_CAP_USER Ta Yes
>>> +.It PMC_CAP_WRITE Ta Yes
>>> +.El
>>> +.Ss Event Qualifiers
>>> +There is no supported event qualifier.
>>> +.Pp
>>> +The event specifiers supported by software are:
>>> +.Bl -tag -width indent
>>> +.It Li CLOCK.HARD
>>> +Hard clock ticks.
>>> +.It Li CLOCK.STAT
>>> +Stat clock ticks.
>>> +.It Li LOCK.FAILED
>>> +Lock acquisition failed.
>>> +.It Li PAGE_FAULT.ALL
>>> +All page fault type.
>>> +.It Li PAGE_FAULT.READ
>>> +Read page fault.
>>> +.It Li PAGE_FAULT.WRITE
>>> +Write page fault.
>>> +.El
>>> +.Sh SEE ALSO
>>> +.Xr pmc 3 ,
>>> +.Xr pmc.atom 3 ,
>>> +.Xr pmc.core 3 ,
>>> +.Xr pmc.iaf 3 ,
>>> +.Xr pmc.ucf 3 ,
>>> +.Xr pmc.k7 3 ,
>>> +.Xr pmc.k8 3 ,
>>> +.Xr pmc.p4 3 ,
>>> +.Xr pmc.p5 3 ,
>>> +.Xr pmc.p6 3 ,
>>> +.Xr pmc.corei7 3 ,
>>> +.Xr pmc.corei7uc 3 ,
>>> +.Xr pmc.westmereuc 3 ,
>>> +.Xr pmc.tsc 3 ,
>>> +.Xr pmc_cpuinfo 3 ,
>>> +.Xr pmclog 3 ,
>>> +.Xr hwpmc 4
>>> +.Sh HISTORY
>>> +The
>>> +.Nm pmc
>>> +library first appeared in
>>> +.Fx 6.0 .
>>> +.Sh AUTHORS
>>> +The
>>> +.Lb libpmc
>>> +library was written by
>>> +.An "Joseph Koshy"
>>> +.Aq [hidden email] .
>>> +Software PMC was written by
>>> +.An "Fabien Thomas"
>>> +.Aq [hidden email] .
>>>
>>> Modified: head/lib/libpmc/pmc.tsc.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -68,6 +68,7 @@ maps to the TSC.
>>>  .Xr pmc.p4 3 ,
>>>  .Xr pmc.p5 3 ,
>>>  .Xr pmc.p6 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmclog 3 ,
>>>  .Xr hwpmc 4
>>>  .Sh HISTORY
>>>
>>> Modified: head/lib/libpmc/pmc.ucf.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -96,6 +96,7 @@ offset C0H under device number 0 and Fun
>>>  .Xr pmc.corei7uc 3 ,
>>>  .Xr pmc.westmere 3 ,
>>>  .Xr pmc.westmereuc 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.westmere.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -1381,6 +1381,7 @@ Counts number of SID integer 64 bit shif
>>>  .Xr pmc.corei7 3 ,
>>>  .Xr pmc.corei7uc 3 ,
>>>  .Xr pmc.westmereuc 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.westmereuc.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -1066,6 +1066,7 @@ disabled.
>>>  .Xr pmc.corei7 3 ,
>>>  .Xr pmc.corei7uc 3 ,
>>>  .Xr pmc.westmere 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr pmc.tsc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>>
>>> Modified: head/lib/libpmc/pmc.xscale.3
>>> ==============================================================================
>>> --- head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -134,6 +134,7 @@ and the underlying hardware events used.
>>>  .Xr pmc 3 ,
>>>  .Xr pmc_cpuinfo 3 ,
>>>  .Xr pmclog 3 ,
>>> +.Xr pmc.soft 3 ,
>>>  .Xr hwpmc 4
>>>  .Sh HISTORY
>>>  The
>>>
>>> Modified: head/lib/libpmc/pmclog.c
>>> ==============================================================================
>>> --- head/lib/libpmc/pmclog.c    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmclog.c    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -369,6 +369,12 @@ pmclog_get_event(void *cookie, char **da
>>>                    == NULL)
>>>                        goto error;
>>>                break;
>>> +       case PMCLOG_TYPE_PMCALLOCATEDYN:
>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_pmcid);
>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_event);
>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_flags);
>>> +               PMCLOG_READSTRING(le,ev->pl_u.pl_ad.pl_evname,PMC_NAME_MAX);
>>> +               break;
>>>        case PMCLOG_TYPE_PMCATTACH:
>>>                PMCLOG_GET_PATHLEN(pathlen,evlen,pmclog_pmcattach);
>>>                PMCLOG_READ32(le,ev->pl_u.pl_t.pl_pmcid);
>>>
>>> Modified: head/lib/libpmc/pmclog.h
>>> ==============================================================================
>>> --- head/lib/libpmc/pmclog.h    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/lib/libpmc/pmclog.h    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -88,6 +88,13 @@ struct pmclog_ev_pmcallocate {
>>>        pmc_id_t        pl_pmcid;
>>>  };
>>>
>>> +struct pmclog_ev_pmcallocatedyn {
>>> +       uint32_t        pl_event;
>>> +       char            pl_evname[PMC_NAME_MAX];
>>> +       uint32_t        pl_flags;
>>> +       pmc_id_t        pl_pmcid;
>>> +};
>>> +
>>>  struct pmclog_ev_pmcattach {
>>>        pmc_id_t        pl_pmcid;
>>>        pid_t           pl_pid;
>>> @@ -146,6 +153,7 @@ struct pmclog_ev {
>>>                struct pmclog_ev_map_out        pl_mo;
>>>                struct pmclog_ev_pcsample       pl_s;
>>>                struct pmclog_ev_pmcallocate    pl_a;
>>> +               struct pmclog_ev_pmcallocatedyn pl_ad;
>>>                struct pmclog_ev_pmcattach      pl_t;
>>>                struct pmclog_ev_pmcdetach      pl_d;
>>>                struct pmclog_ev_proccsw        pl_c;
>>>
>>> Modified: head/sys/amd64/amd64/trap.c
>>> ==============================================================================
>>> --- head/sys/amd64/amd64/trap.c Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/amd64/amd64/trap.c Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
>>>  #include <sys/vmmeter.h>
>>>  #ifdef HWPMC_HOOKS
>>>  #include <sys/pmckern.h>
>>> +PMC_SOFT_DEFINE( , , page_fault, all);
>>> +PMC_SOFT_DEFINE( , , page_fault, read);
>>> +PMC_SOFT_DEFINE( , , page_fault, write);
>>>  #endif
>>>
>>>  #include <vm/vm.h>
>>> @@ -743,8 +746,20 @@ trap_pfault(frame, usermode)
>>>                 */
>>>                rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
>>>        }
>>> -       if (rv == KERN_SUCCESS)
>>> +       if (rv == KERN_SUCCESS) {
>>> +#ifdef HWPMC_HOOKS
>>> +               if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
>>> +                       PMC_SOFT_CALL_TF( , , page_fault, all, frame);
>>> +                       if (ftype == VM_PROT_READ)
>>> +                               PMC_SOFT_CALL_TF( , , page_fault, read,
>>> +                                   frame);
>>> +                       else
>>> +                               PMC_SOFT_CALL_TF( , , page_fault, write,
>>> +                                   frame);
>>> +               }
>>> +#endif
>>>                return (0);
>>> +       }
>>>  nogo:
>>>        if (!usermode) {
>>>                if (td->td_intr_nesting_level == 0 &&
>>>
>>> Modified: head/sys/amd64/include/pmc_mdep.h
>>> ==============================================================================
>>> --- head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -50,13 +50,13 @@ struct pmc_mdep;
>>>  * measurement architecture have PMCs of the following classes: TSC,
>>>  * IAF, IAP, UCF and UCP.
>>>  */
>>> -#define        PMC_MDEP_CLASS_INDEX_TSC        0
>>> -#define        PMC_MDEP_CLASS_INDEX_K8         1
>>> -#define        PMC_MDEP_CLASS_INDEX_P4         1
>>> -#define        PMC_MDEP_CLASS_INDEX_IAP        1
>>> -#define        PMC_MDEP_CLASS_INDEX_IAF        2
>>> -#define        PMC_MDEP_CLASS_INDEX_UCP        3
>>> -#define        PMC_MDEP_CLASS_INDEX_UCF        4
>>> +#define        PMC_MDEP_CLASS_INDEX_TSC        1
>>> +#define        PMC_MDEP_CLASS_INDEX_K8         2
>>> +#define        PMC_MDEP_CLASS_INDEX_P4         2
>>> +#define        PMC_MDEP_CLASS_INDEX_IAP        2
>>> +#define        PMC_MDEP_CLASS_INDEX_IAF        3
>>> +#define        PMC_MDEP_CLASS_INDEX_UCP        4
>>> +#define        PMC_MDEP_CLASS_INDEX_UCF        5
>>>
>>>  /*
>>>  * On the amd64 platform we support the following PMCs.
>>> @@ -119,6 +119,15 @@ union pmc_md_pmc {
>>>
>>>  #define        PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
>>>
>>> +/* Build a fake kernel trapframe from current instruction pointer. */
>>> +#define PMC_FAKE_TRAPFRAME(TF)                                         \
>>> +       do {                                                            \
>>> +       (TF)->tf_cs = 0; (TF)->tf_rflags = 0;                           \
>>> +       __asm __volatile("movq %%rbp,%0" : "=r" ((TF)->tf_rbp));        \
>>> +       __asm __volatile("movq %%rsp,%0" : "=r" ((TF)->tf_rsp));        \
>>> +       __asm __volatile("call 1f \n\t1: pop %0" : "=r"((TF)->tf_rip)); \
>>> +       } while (0)
>>> +
>>>  /*
>>>  * Prototypes
>>>  */
>>>
>>> Modified: head/sys/arm/include/pmc_mdep.h
>>> ==============================================================================
>>> --- head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -29,7 +29,7 @@
>>>  #ifndef _MACHINE_PMC_MDEP_H_
>>>  #define        _MACHINE_PMC_MDEP_H_
>>>
>>> -#define        PMC_MDEP_CLASS_INDEX_XSCALE     0
>>> +#define        PMC_MDEP_CLASS_INDEX_XSCALE     1
>>>  /*
>>>  * On the ARM platform we support the following PMCs.
>>>  *
>>>
>>> Modified: head/sys/conf/files
>>> ==============================================================================
>>> --- head/sys/conf/files Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/conf/files Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -1260,6 +1260,7 @@ dev/hme/if_hme_sbus.c             optional hme sbus
>>>  dev/hptiop/hptiop.c            optional hptiop scbus
>>>  dev/hwpmc/hwpmc_logging.c      optional hwpmc
>>>  dev/hwpmc/hwpmc_mod.c          optional hwpmc
>>> +dev/hwpmc/hwpmc_soft.c         optional hwpmc
>>>  dev/ichsmb/ichsmb.c            optional ichsmb
>>>  dev/ichsmb/ichsmb_pci.c                optional ichsmb pci
>>>  dev/ida/ida.c                  optional ida
>>>
>>> Modified: head/sys/dev/hwpmc/hwpmc_amd.c
>>> ==============================================================================
>>> --- head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -687,7 +687,8 @@ amd_intr(int cpu, struct trapframe *tf)
>>>                wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
>>>
>>>                /* Restart the counter if logging succeeded. */
>>> -               error = pmc_process_interrupt(cpu, pm, tf, TRAPF_USERMODE(tf));
>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>> +                   TRAPF_USERMODE(tf));
>>>                if (error == 0)
>>>                        wrmsr(evsel, config | AMD_PMC_ENABLE);
>>>        }
>>> @@ -874,7 +875,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int c
>>>  struct pmc_mdep *
>>>  pmc_amd_initialize(void)
>>>  {
>>> -       int classindex, error, i, nclasses, ncpus;
>>> +       int classindex, error, i, ncpus;
>>>        struct pmc_classdep *pcd;
>>>        enum pmc_cputype cputype;
>>>        struct pmc_mdep *pmc_mdep;
>>> @@ -926,12 +927,9 @@ pmc_amd_initialize(void)
>>>         * These processors have two classes of PMCs: the TSC and
>>>         * programmable PMCs.
>>>         */
>>> -       nclasses = 2;
>>> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses * sizeof (struct pmc_classdep),
>>> -           M_PMC, M_WAITOK|M_ZERO);
>>> +       pmc_mdep = pmc_mdep_alloc(2);
>>>
>>>        pmc_mdep->pmd_cputype = cputype;
>>> -       pmc_mdep->pmd_nclass  = nclasses;
>>>
>>>        ncpus = pmc_cpu_max();
>>>
>>>
>>> Modified: head/sys/dev/hwpmc/hwpmc_core.c
>>> ==============================================================================
>>> --- head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -2239,7 +2239,7 @@ core_intr(int cpu, struct trapframe *tf)
>>>                if (pm->pm_state != PMC_STATE_RUNNING)
>>>                        continue;
>>>
>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>                    TRAPF_USERMODE(tf));
>>>
>>>                v = pm->pm_sc.pm_reloadcount;
>>> @@ -2326,7 +2326,7 @@ core2_intr(int cpu, struct trapframe *tf
>>>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>>>                        continue;
>>>
>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>                    TRAPF_USERMODE(tf));
>>>                if (error)
>>>                        intrenable &= ~flag;
>>> @@ -2354,7 +2354,7 @@ core2_intr(int cpu, struct trapframe *tf
>>>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>>>                        continue;
>>>
>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>                    TRAPF_USERMODE(tf));
>>>                if (error)
>>>                        intrenable &= ~flag;
>>>
>>> Modified: head/sys/dev/hwpmc/hwpmc_intel.c
>>> ==============================================================================
>>> --- head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -162,12 +162,10 @@ pmc_intel_initialize(void)
>>>                return (NULL);
>>>        }
>>>
>>> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses *
>>> -           sizeof(struct pmc_classdep), M_PMC, M_WAITOK|M_ZERO);
>>> +       /* Allocate base class and initialize machine dependent struct */
>>> +       pmc_mdep = pmc_mdep_alloc(nclasses);
>>>
>>>        pmc_mdep->pmd_cputype    = cputype;
>>> -       pmc_mdep->pmd_nclass     = nclasses;
>>> -
>>>        pmc_mdep->pmd_switch_in  = intel_switch_in;
>>>        pmc_mdep->pmd_switch_out = intel_switch_out;
>>>
>>>
>>> Modified: head/sys/dev/hwpmc/hwpmc_logging.c
>>> ==============================================================================
>>> --- head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -129,6 +129,7 @@ static struct mtx pmc_kthread_mtx;  /* sl
>>>
>>>  /* Emit a string.  Caution: does NOT update _le, so needs to be last */
>>>  #define        PMCLOG_EMITSTRING(S,L)  do { bcopy((S), _le, (L)); } while (0)
>>> +#define        PMCLOG_EMITNULLSTRING(L) do { bzero(_le, (L)); } while (0)
>>>
>>>  #define        PMCLOG_DESPATCH(PO)                                             \
>>>                pmclog_release((PO));                                   \
>>> @@ -835,16 +836,33 @@ void
>>>  pmclog_process_pmcallocate(struct pmc *pm)
>>>  {
>>>        struct pmc_owner *po;
>>> +       struct pmc_soft *ps;
>>>
>>>        po = pm->pm_owner;
>>>
>>>        PMCDBG(LOG,ALL,1, "pm=%p", pm);
>>>
>>> -       PMCLOG_RESERVE(po, PMCALLOCATE, sizeof(struct pmclog_pmcallocate));
>>> -       PMCLOG_EMIT32(pm->pm_id);
>>> -       PMCLOG_EMIT32(pm->pm_event);
>>> -       PMCLOG_EMIT32(pm->pm_flags);
>>> -       PMCLOG_DESPATCH(po);
>>> +       if (PMC_TO_CLASS(pm) == PMC_CLASS_SOFT) {
>>> +               PMCLOG_RESERVE(po, PMCALLOCATEDYN,
>>> +                   sizeof(struct pmclog_pmcallocatedyn));
>>> +               PMCLOG_EMIT32(pm->pm_id);
>>> +               PMCLOG_EMIT32(pm->pm_event);
>>> +               PMCLOG_EMIT32(pm->pm_flags);
>>> +               ps = pmc_soft_ev_acquire(pm->pm_event);
>>> +               if (ps != NULL)
>>> +                       PMCLOG_EMITSTRING(ps->ps_ev.pm_ev_name,PMC_NAME_MAX);
>>> +               else
>>> +                       PMCLOG_EMITNULLSTRING(PMC_NAME_MAX);
>>> +               pmc_soft_ev_release(ps);
>>> +               PMCLOG_DESPATCH(po);
>>> +       } else {
>>> +               PMCLOG_RESERVE(po, PMCALLOCATE,
>>> +                   sizeof(struct pmclog_pmcallocate));
>>> +               PMCLOG_EMIT32(pm->pm_id);
>>> +               PMCLOG_EMIT32(pm->pm_event);
>>> +               PMCLOG_EMIT32(pm->pm_flags);
>>> +               PMCLOG_DESPATCH(po);
>>> +       }
>>>  }
>>>
>>>  void
>>>
>>> Modified: head/sys/dev/hwpmc/hwpmc_mips.c
>>> ==============================================================================
>>> --- head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -287,7 +287,7 @@ mips_pmc_intr(int cpu, struct trapframe
>>>                retval = 1;
>>>                if (pm->pm_state != PMC_STATE_RUNNING)
>>>                        continue;
>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>                    TRAPF_USERMODE(tf));
>>>                if (error) {
>>>                        /* Clear/disable the relevant counter */
>>>
>>> Modified: head/sys/dev/hwpmc/hwpmc_mod.c
>>> ==============================================================================
>>> --- head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:49:11 2012        (r233627)
>>> +++ head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:58:30 2012        (r233628)
>>> @@ -70,6 +70,8 @@ __FBSDID("$FreeBSD$");
>>>  #include <vm/vm_map.h>
>>>  #include <vm/vm_object.h>
>>>
>>> +#include "hwpmc_soft.h"
>>> +
>>>  /*
>>>  * Types
>>>  */
>>> @@ -182,7 +184,7 @@ static int  pmc_attach_one_process(struct
>>>  static int     pmc_can_allocate_rowindex(struct proc *p, unsigned int ri,
>>>     int cpu);
>>>  static int     pmc_can_attach(struct pmc *pm, struct proc *p);
>>> -static void    pmc_capture_user_callchain(int cpu, struct trapframe *tf);
>>> +static void    pmc_capture_user_callchain(int cpu, int soft, struct trapframe *tf);
>>>  static void    pmc_cleanup(void);
>>>  static int     pmc_detach_process(struct proc *p, struct pmc *pm);
>>>  static int     pmc_detach_one_process(struct proc *p, struct pmc *pm,
>>> @@ -206,7 +208,7 @@ static void pmc_process_csw_out(struct t
>>>  static void    pmc_process_exit(void *arg, struct proc *p);
>>>  static void    pmc_process_fork(void *arg, struct proc *p1,
>>>     struct proc *p2, int n);
>>> -static void    pmc_process_samples(int cpu);
>>> +static void    pmc_process_samples(int cpu, int soft);
>>>  static void    pmc_release_pmc_descriptor(struct pmc *pmc);
>>>  static void    pmc_remove_owner(struct pmc_owner *po);
>>>  static void    pmc_remove_process_descriptor(struct pmc_process *pp);
>>> @@ -218,12 +220,16 @@ static int        pmc_stop(struct pmc *pm);
>>>  static int     pmc_syscall_handler(struct thread *td, void *syscall_args);
>>>  static void    pmc_unlink_target_process(struct pmc *pmc,
>>>     struct pmc_process *pp);
>>> +static int generic_switch_in(struct pmc_cpu *pc, struct pmc_process *pp);
>>> +static int generic_switch_out(struct pmc_cpu *pc, struct pmc_process *pp);
>>> +static struct pmc_mdep *pmc_generic_cpu_initialize(void);
>>> +static void pmc_generic_cpu_finalize(struct pmc_mdep *md);
>>>
>>>  /*
>>>  * Kernel tunables and sysctl(8) interface.
>>>  */
>>>
>>> -SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0, "HWPMC parameters");
>>> +SYSCTL_DECL(_kern_hwpmc);
>>>
>>>  static int pmc_callchaindepth = PMC_CALLCHAIN_DEPTH;
>>>  TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "callchaindepth", &pmc_callchaindepth);
>>> @@ -1833,7 +1839,9 @@ const char *pmc_hooknames[] = {
>>>        "KLDUNLOAD",
>>>        "MMAP",
>>>        "MUNMAP",
>>> -       "CALLCHAIN"
>>> +       "CALLCHAIN-NMI",
>>> +       "CALLCHAIN-SOFT",
>>> +       "SOFTSAMPLING"
>>>  };
>>>  #endif
>>>
>>> @@ -1992,7 +2000,8 @@ pmc_hook_handler(struct thread *td, int
>>>                 * lose the interrupt sample.
>>>                 */
>>>                CPU_CLR_ATOMIC(PCPU_GET(cpuid), &pmc_cpumask);
>>> -               pmc_process_samples(PCPU_GET(cpuid));
>>> +               pmc_process_samples(PCPU_GET(cpuid), PMC_HR);
>>> +               pmc_process_samples(PCPU_GET(cpuid), PMC_SR);
>>>                break;
>>>
>>>
>>> @@ -2022,11 +2031,30 @@ pmc_hook_handler(struct thread *td, int
>>>                 */
>>>                KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>>>                    __LINE__));
>>> -               pmc_capture_user_callchain(PCPU_GET(cpuid),
>>> +
>>> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_HR,
>>>                    (struct trapframe *) arg);
>>>                td->td_pflags &= ~TDP_CALLCHAIN;
>>>                break;
>>>
>>> +       case PMC_FN_USER_CALLCHAIN_SOFT:
>>> +               /*
>>> +                * Record a call chain.
>>> +                */
>>> +               KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>>> +                   __LINE__));
>>> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_SR,
>>> +                   (struct trapframe *) arg);
>>> +               td->td_pflags &= ~TDP_CALLCHAIN;
>>> +               break;
>>> +
>>> +       case PMC_FN_SOFT_SAMPLING:
>>> +               /*
>>> +                * Call soft PMC sampling intr.
>>> +                */
>>> +               pmc_soft_intr((struct pmckern_soft *) arg);
>>> +               break;
>>> +
>>>        default:
>>>  #ifdef DEBUG
>>>                KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
>>> @@ -2221,18 +2249,17 @@ pmc_destroy_pmc_descriptor(struct pmc *p
>>>  static void
>>>  pmc_wait_for_pmc_idle(struct pmc *pm)
>>>  {
>>> -#ifdef DEBUG
>>> +#ifdef DEBUG
>>>        volatile int maxloop;
>>>
>>>        maxloop = 100 * pmc_cpu_max();
>>>  #endif
>>> -
>>>        /*
>>>         * Loop (with a forced context switch) till the PMC's runcount
>>>         * comes down to zero.
>>>         */
>>>        while (atomic_load_acq_32(&pm->pm_runcount) > 0) {
>>> -#ifdef DEBUG
>>> +#ifdef DEBUG
>>>                maxloop--;
>>>                KASSERT(maxloop > 0,
>>>                    ("[pmc,%d] (ri%d, rc%d) waiting too long for "
>>> @@ -2972,6 +2999,53 @@ pmc_syscall_handler(struct thread *td, v
>>>        }
>>>        break;
>>>
>>> +       /*
>>> +        * Retrieve soft events list.
>>> +        */
>>> +       case PMC_OP_GETDYNEVENTINFO:
>>> +       {
>>> +               enum pmc_class                  cl;
>>> +               enum pmc_event                  ev;
>>> +               struct pmc_op_getdyneventinfo   *gei;
>>> +               struct pmc_dyn_event_descr      dev;
>>> +               struct pmc_soft                 *ps;
>>> +               uint32_t                        nevent;
>>> +
>>> +               sx_assert(&pmc_sx, SX_LOCKED);
>>> +
>>> +               gei = (struct pmc_op_getdyneventinfo *) arg;
>>> +
>>> +               if ((error = copyin(&gei->pm_class, &cl, sizeof(cl))) != 0)
>>> +                       break;
>>> +
>>> +               /* Only SOFT class is dynamic. */
>>> +               if (cl != PMC_CLASS_SOFT) {
>>> +                       error = EINVAL;
>>> +                       break;
>>> +               }
>>> +
>>> +               nevent = 0;
>>> +               for (ev = PMC_EV_SOFT_FIRST; ev <= PMC_EV_SOFT_LAST; ev++) {
>>> +                       ps = pmc_soft_ev_acquire(ev);
>>> +                       if (ps == NULL)
>>> +                               continue;
>>> +                       bcopy(&ps->ps_ev, &dev, sizeof(dev));
>>> +                       pmc_soft_ev_release(ps);
>>> +
>>> +                       error = copyout(&dev,
>>> +                           &gei->pm_events[nevent],
>>> +                           sizeof(struct pmc_dyn_event_descr));
>>> +                       if (error != 0)
>>> +                               break;
>>> +                       nevent++;
>>> +               }
>>> +               if (error != 0)
>>> +                       break;
>>> +
>>> +               error = copyout(&nevent, &gei->pm_nevent,
>>>
>>> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
>
>
>
> --
> Monthadar Al Jaberi
> <RSPRO_USB_PROD>


patch-fixsoft (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: svn commit: r233628 - in head: lib/libpmc sys/amd64/amd64 sys/amd64/include sys/arm/include sys/conf sys/dev/hwpmc sys/i386/i386 sys/i386/include sys/kern sys/mips/include sys/modules/hwpmc sys/pow...

Monthadar Al Jaberi
On Mon, Apr 23, 2012 at 9:47 AM, Fabien Thomas <[hidden email]> wrote:
> Hi,
>
> The rumors seems true :)
> Can you try the patch attached (I cannot test as i've no MIPS hardware) ?

my RSPRO boots fine now, thank you :)

>
> Thanks,
> Fabien
>
>
>> On Mon, Apr 23, 2012 at 8:44 AM, Adrian Chadd <[hidden email]> wrote:
>>> Hi Fabien,
>>>
>>> I've heard some rumours that this broke hwpmc support for mips24k.
>>>
>>> Monthadar, can you please provide some background info for this?
>>>
>>
>> This is the log output
>>
>> Using default protocol (TFTP)
>> Entry point: 0x80050100, address range: 0x80050000-0x804f1dcc
>> RedBoot> exec
>> Now booting linux kernel:
>> Base address 0x80050000 Entry 0x80050100
>> memsize=0x08000000
>> modetty0=0,n,8,1,hw
>> board=RouterStation PRO
>> ethaddr=00.15.6d.c8.c9.2e
>> CPU platform: Atheros AR7161 rev 2
>> CPU Frequency=720 MHz
>> CPU DDR Frequency=360 MHz
>> CPU AHB Frequency=180 MHz
>> platform frequency: 720000000
>> arguments:
>>  a0 = 00000002
>>  a1 = 80050028
>>  a2 = 80050000
>>  a3 = 00000001
>> Cmd line:  �������m���������������_}������߾q��������������� �����������������߿���������_�w���� �����?-����{������~��
>> Environment:
>>  memsize = 0x08000000
>>  modetty0 = 0,n,8,1,hw
>>  ethaddr = 00.15.6d.c8.c9.2e
>>  board = RouterStation PRO
>> Cache info:
>>  picache_stride    = 4096
>>  picache_loopcount = 16
>>  pdcache_stride    = 4096
>>  pdcache_loopcount = 8
>> cpu0: MIPS Technologies processor v116.147
>>  MMU: Standard TLB, 16 entries
>>  L1 i-cache: 4 ways of 512 sets, 32 bytes per line
>>  L1 d-cache: 4 ways of 256 sets, 32 bytes per line
>>  Config1=0x9ee3519e<PerfCount,WatchRegs,MIPS16,EJTAG>
>>  Config3=0x20
>> KDB: debugger backends: ddb
>> KDB: current backend: ddb
>> Copyright (c) 1992-2012 The FreeBSD Project.
>> Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
>>       The Regents of the University of California. All rights reserved.
>> FreeBSD is a registered trademark of The FreeBSD Foundation.
>> FreeBSD 10.0-CURRENT #12: Fri Apr 20 18:03:16 CEST 2012
>>    root@freebsd-re-9:/usr/obj/mips.mips/usr/src/sys/RSPRO_USB_PROD mips
>> WARNING: WITNESS option enabled, expect reduced performance.
>> MEMGUARD DEBUGGING ALLOCATOR INITIALIZED:
>>       MEMGUARD map base: 0xc0800000
>>       MEMGUARD map limit: 0xc1c00000
>>       MEMGUARD map size: 20480 KBytes
>> real memory  = 134217728 (131072K bytes)
>> avail memory = 123117568 (117MB)
>> random device not loaded; using insecure entropy
>> nexus0: <MIPS32 root nexus>
>> clock0: <Generic MIPS32 ticker> on nexus0
>> Timecounter "MIPS32" frequency 360000000 Hz quality 800
>> Event timer "MIPS32" frequency 360000000 Hz quality 800
>> apb0 at irq 4 on nexus0
>> uart0: <16550 or compatible> on apb0
>> uart0: console (115200,n,8,1)
>> gpio0: <Atheros AR71XX GPIO driver> on apb0
>> gpio0: [GIANT-LOCKED]
>> gpio0: gpio pinmask=0x0
>> gpioc0: <GPIO controller> on gpio0
>> gpiobus0: <GPIO bus> on gpio0
>> ehci0: <AR71XX Integrated USB 2.0 controller> at mem
>> 0x1b000000-0x1bffffff irq 1 on nexus0
>> usbus0: set host controller mode
>> usbus0: EHCI version 1.0
>> usbus0: set host controller mode
>> usbus0 on ehci0
>> pcib0 at irq 0 on nexus0
>> pci0: <PCI bus> on pcib0
>> pci0: <old, non-VGA display device> at device 0.0 (no driver attached)
>> ath0: <Atheros 5413> irq 0 at device 17.0 on pci0
>> ath0: AR5413 mac 10.5 RF5413 phy 6.1
>> ath0: 2GHz radio: 0x0000; 5GHz radio: 0x0063
>> arge0: <Atheros AR71xx built-in ethernet interface> at mem
>> 0x19000000-0x19000fff irq 2 on nexus0
>> arge0: No PHY specified, using mask 16
>> miibus0: <MII bus> on arge0
>> ukphy0: <Generic IEEE 802.3u media interface> PHY 4 on miibus0
>> ukphy0:  none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX,
>> 1000baseT-FDX, 1000baseT-FDX-master, auto
>> arge0: Ethernet address: 00:15:6d:c8:c9:2e
>> arge1: <Atheros AR71xx built-in ethernet interface> at mem
>> 0x1a000000-0x1a000fff irq 3 on nexus0
>> arge1: No PHY specified, using mask 15
>> arge1: Ethernet address: 00:15:6d:c8:c9:2f
>> spi0: <AR71XX SPI> at mem 0x1f000000-0x1f00000f on nexus0
>> spibus0: <spibus bus> on spi0
>> mx25l0: <M25Pxx Flash Family> at cs 0 on spibus0
>> mx25l0: mx25ll128, sector 65536 bytes, 256 sectors
>> ar71xx_wdog0: <Atheros AR71XX watchdog timer> on nexus0
>> Timecounters tick every 1.000 msec
>> usbus0: 480Mbps High Speed USB v2.0
>> ugen0.1: <Atheros> at usbus0
>> uhub0: <Atheros EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus0
>> panic: [pmc,4816] npmc miscomputed: ri=0, md->npmc=2
>> KDB: enter: panic
>> [ thread pid 0 tid 100000 ]
>> Stopped at      kdb_enter+0x4c: lui     at,0x8050
>> db> tr
>> Tracing pid 0 tid 100000 td 0x804f76d0
>> db_trace_thread+30 (?,?,?,?) ra 8068b94800000018 sp 0 sz 0
>> 80075adc+114 (0,?,ffffffff,?) ra 8068b96000000020 sp 100000000 sz 1
>> 80074e24+388 (?,?,?,?) ra 8068b980000000a8 sp 0 sz 0
>> db_command_loop+70 (?,?,?,?) ra 8068ba2800000018 sp 0 sz 0
>> 80077900+f4 (?,?,?,?) ra 8068ba40000001a8 sp 0 sz 0
>> kdb_trap+110 (?,?,?,?) ra 8068bbe800000030 sp 0 sz 0
>> trap+c7c (?,?,?,?) ra 8068bc18000000b8 sp 0 sz 0
>> MipsKernGenException+134 (0,4,8043b1d4,119) ra 8068bcd0000000c8 sp
>> 100000001 sz 1
>> kdb_enter+4c (?,?,?,?) ra 8068bd9800000018 sp 0 sz 0
>> panic+11c (?,12d0,0,2) ra 8068bdb000000028 sp 1 sz 1
>> 800e8ca8+274 (?,?,?,?) ra 8068bdd800000038 sp 0 sz 0
>> syscall_module_handler+b8 (?,?,?,?) ra 8068be1000000028 sp 0 sz 0
>> module_register_init+9c (?,?,?,?) ra 8068be3800000028 sp 0 sz 0
>> mi_startup+138 (?,?,?,?) ra 8068be6000000020 sp 0 sz 0
>> _start+90 (?,?,?,?) ra 8068be8000000000 sp 0 sz 0
>> pid 0
>> db>
>>
>>> Thanks,
>>>
>>>
>>>
>>> adrian
>>>
>>> On 28 March 2012 13:58, Fabien Thomas <[hidden email]> wrote:
>>>> Author: fabient
>>>> Date: Wed Mar 28 20:58:30 2012
>>>> New Revision: 233628
>>>> URL: http://svn.freebsd.org/changeset/base/233628
>>>>
>>>> Log:
>>>>  Add software PMC support.
>>>>
>>>>  New kernel events can be added at various location for sampling or counting.
>>>>  This will for example allow easy system profiling whatever the processor is
>>>>  with known tools like pmcstat(8).
>>>>
>>>>  Simultaneous usage of software PMC and hardware PMC is possible, for example
>>>>  looking at the lock acquire failure, page fault while sampling on
>>>>  instructions.
>>>>
>>>>  Sponsored by: NETASQ
>>>>  MFC after:    1 month
>>>>
>>>> Added:
>>>>  head/lib/libpmc/pmc.soft.3   (contents, props changed)
>>>>  head/sys/dev/hwpmc/hwpmc_soft.c   (contents, props changed)
>>>>  head/sys/dev/hwpmc/hwpmc_soft.h   (contents, props changed)
>>>> Modified:
>>>>  head/lib/libpmc/Makefile
>>>>  head/lib/libpmc/libpmc.c
>>>>  head/lib/libpmc/pmc.3
>>>>  head/lib/libpmc/pmc.atom.3
>>>>  head/lib/libpmc/pmc.core.3
>>>>  head/lib/libpmc/pmc.core2.3
>>>>  head/lib/libpmc/pmc.corei7.3
>>>>  head/lib/libpmc/pmc.corei7uc.3
>>>>  head/lib/libpmc/pmc.iaf.3
>>>>  head/lib/libpmc/pmc.k7.3
>>>>  head/lib/libpmc/pmc.k8.3
>>>>  head/lib/libpmc/pmc.mips24k.3
>>>>  head/lib/libpmc/pmc.octeon.3
>>>>  head/lib/libpmc/pmc.p4.3
>>>>  head/lib/libpmc/pmc.p5.3
>>>>  head/lib/libpmc/pmc.p6.3
>>>>  head/lib/libpmc/pmc.sandybridge.3
>>>>  head/lib/libpmc/pmc.sandybridgeuc.3
>>>>  head/lib/libpmc/pmc.tsc.3
>>>>  head/lib/libpmc/pmc.ucf.3
>>>>  head/lib/libpmc/pmc.westmere.3
>>>>  head/lib/libpmc/pmc.westmereuc.3
>>>>  head/lib/libpmc/pmc.xscale.3
>>>>  head/lib/libpmc/pmclog.c
>>>>  head/lib/libpmc/pmclog.h
>>>>  head/sys/amd64/amd64/trap.c
>>>>  head/sys/amd64/include/pmc_mdep.h
>>>>  head/sys/arm/include/pmc_mdep.h
>>>>  head/sys/conf/files
>>>>  head/sys/dev/hwpmc/hwpmc_amd.c
>>>>  head/sys/dev/hwpmc/hwpmc_core.c
>>>>  head/sys/dev/hwpmc/hwpmc_intel.c
>>>>  head/sys/dev/hwpmc/hwpmc_logging.c
>>>>  head/sys/dev/hwpmc/hwpmc_mips.c
>>>>  head/sys/dev/hwpmc/hwpmc_mod.c
>>>>  head/sys/dev/hwpmc/hwpmc_piv.c
>>>>  head/sys/dev/hwpmc/hwpmc_powerpc.c
>>>>  head/sys/dev/hwpmc/hwpmc_ppro.c
>>>>  head/sys/dev/hwpmc/hwpmc_tsc.c
>>>>  head/sys/dev/hwpmc/hwpmc_x86.c
>>>>  head/sys/dev/hwpmc/hwpmc_xscale.c
>>>>  head/sys/dev/hwpmc/pmc_events.h
>>>>  head/sys/i386/i386/trap.c
>>>>  head/sys/i386/include/pmc_mdep.h
>>>>  head/sys/kern/kern_clock.c
>>>>  head/sys/kern/kern_lock.c
>>>>  head/sys/kern/kern_mutex.c
>>>>  head/sys/kern/kern_pmc.c
>>>>  head/sys/kern/kern_rwlock.c
>>>>  head/sys/kern/kern_sx.c
>>>>  head/sys/kern/subr_trap.c
>>>>  head/sys/mips/include/pmc_mdep.h
>>>>  head/sys/modules/hwpmc/Makefile
>>>>  head/sys/powerpc/include/pmc_mdep.h
>>>>  head/sys/sys/pmc.h
>>>>  head/sys/sys/pmckern.h
>>>>  head/sys/sys/pmclog.h
>>>>  head/usr.sbin/pmcstat/pmcstat_log.c
>>>>
>>>> Modified: head/lib/libpmc/Makefile
>>>> ==============================================================================
>>>> --- head/lib/libpmc/Makefile    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/Makefile    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -20,6 +20,7 @@ MAN+= pmc_read.3
>>>>  MAN+=  pmc_set.3
>>>>  MAN+=  pmc_start.3
>>>>  MAN+=  pmclog.3
>>>> +MAN+=  pmc.soft.3
>>>>
>>>>  # PMC-dependent manual pages
>>>>  .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
>>>>
>>>> Modified: head/lib/libpmc/libpmc.c
>>>> ==============================================================================
>>>> --- head/lib/libpmc/libpmc.c    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/libpmc.c    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -77,11 +77,12 @@ static int tsc_allocate_pmc(enum pmc_eve
>>>>  static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>>>>     struct pmc_op_pmcallocate *_pmc_config);
>>>>  #endif
>>>> -
>>>>  #if defined(__mips__)
>>>>  static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>>>>                             struct pmc_op_pmcallocate *_pmc_config);
>>>>  #endif /* __mips__ */
>>>> +static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>>>> +    struct pmc_op_pmcallocate *_pmc_config);
>>>>
>>>>  #if defined(__powerpc__)
>>>>  static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>>>> @@ -156,6 +157,8 @@ PMC_CLASSDEP_TABLE(octeon, OCTEON);
>>>>  PMC_CLASSDEP_TABLE(ucf, UCF);
>>>>  PMC_CLASSDEP_TABLE(ppc7450, PPC7450);
>>>>
>>>> +static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT];
>>>> +
>>>>  #undef __PMC_EV_ALIAS
>>>>  #define        __PMC_EV_ALIAS(N,CODE)  { N, PMC_EV_##CODE },
>>>>
>>>> @@ -215,21 +218,22 @@ static const struct pmc_event_descr west
>>>>                PMC_CLASS_##C, __VA_ARGS__                      \
>>>>        }
>>>>
>>>> -PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>>> -PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
>>>> -PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>>> -PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>> -PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>> -PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>> -PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
>>>> -PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
>>>> -PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
>>>> -PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC);
>>>> -PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC);
>>>> -PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE);
>>>> -PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K);
>>>> -PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_OCTEON);
>>>> -PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_PPC7450);
>>>> +PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>>> +PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>> +PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>>> +PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>> +PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>> +PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>> +PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>> +PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>> +PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>> +PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>> +PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>> +PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE);
>>>> +PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K);
>>>> +PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON);
>>>> +PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450);
>>>> +PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT);
>>>>
>>>>  static const struct pmc_event_descr tsc_event_table[] =
>>>>  {
>>>> @@ -279,16 +283,24 @@ PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc)
>>>>  #if    defined(__XSCALE__)
>>>>  PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale);
>>>>  #endif
>>>> -
>>>>  #if defined(__mips__)
>>>>  PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips);
>>>>  PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips);
>>>>  #endif /* __mips__ */
>>>> -
>>>>  #if defined(__powerpc__)
>>>>  PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450);
>>>>  #endif
>>>>
>>>> +static struct pmc_class_descr soft_class_table_descr =
>>>> +{
>>>> +       .pm_evc_name  = "SOFT-",
>>>> +       .pm_evc_name_size = sizeof("SOFT-") - 1,
>>>> +       .pm_evc_class = PMC_CLASS_SOFT,
>>>> +       .pm_evc_event_table = NULL,
>>>> +       .pm_evc_event_table_size = 0,
>>>> +       .pm_evc_allocate_pmc = soft_allocate_pmc
>>>> +};
>>>> +
>>>>  #undef PMC_CLASS_TABLE_DESC
>>>>
>>>>  static const struct pmc_class_descr **pmc_class_table;
>>>> @@ -343,9 +355,12 @@ static const char * pmc_state_names[] =
>>>>        __PMC_STATES()
>>>>  };
>>>>
>>>> -static int pmc_syscall = -1;           /* filled in by pmc_init() */
>>>> -
>>>> -static struct pmc_cpuinfo cpu_info;    /* filled in by pmc_init() */
>>>> +/*
>>>> + * Filled in by pmc_init().
>>>> + */
>>>> +static int pmc_syscall = -1;
>>>> +static struct pmc_cpuinfo cpu_info;
>>>> +static struct pmc_op_getdyneventinfo soft_event_info;
>>>>
>>>>  /* Event masks for events */
>>>>  struct pmc_masks {
>>>> @@ -2179,6 +2194,25 @@ tsc_allocate_pmc(enum pmc_event pe, char
>>>>  }
>>>>  #endif
>>>>
>>>> +static struct pmc_event_alias generic_aliases[] = {
>>>> +       EV_ALIAS("instructions",                "SOFT-CLOCK.HARD"),
>>>> +       EV_ALIAS(NULL, NULL)
>>>> +};
>>>> +
>>>> +static int
>>>> +soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
>>>> +    struct pmc_op_pmcallocate *pmc_config)
>>>> +{
>>>> +       (void)ctrspec;
>>>> +       (void)pmc_config;
>>>> +
>>>> +       if (pe < PMC_EV_SOFT_FIRST || pe > PMC_EV_SOFT_LAST)
>>>> +               return (-1);
>>>> +
>>>> +       pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
>>>> +       return (0);
>>>> +}
>>>> +
>>>>  #if    defined(__XSCALE__)
>>>>
>>>>  static struct pmc_event_alias xscale_aliases[] = {
>>>> @@ -2663,6 +2697,10 @@ pmc_event_names_of_class(enum pmc_class
>>>>                ev = ppc7450_event_table;
>>>>                count = PMC_EVENT_TABLE_SIZE(ppc7450);
>>>>                break;
>>>> +       case PMC_CLASS_SOFT:
>>>> +               ev = soft_event_table;
>>>> +               count = soft_event_info.pm_nevent;
>>>> +               break;
>>>>        default:
>>>>                errno = EINVAL;
>>>>                return (-1);
>>>> @@ -2676,6 +2714,7 @@ pmc_event_names_of_class(enum pmc_class
>>>>
>>>>        for (;count--; ev++, names++)
>>>>                *names = ev->pm_ev_name;
>>>> +
>>>>        return (0);
>>>>  }
>>>>
>>>> @@ -2780,11 +2819,34 @@ pmc_init(void)
>>>>                pmc_class_table[n] = NULL;
>>>>
>>>>        /*
>>>> +        * Get soft events list.
>>>> +        */
>>>> +       soft_event_info.pm_class = PMC_CLASS_SOFT;
>>>> +       if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0)
>>>> +               return (pmc_syscall = -1);
>>>> +
>>>> +       /* Map soft events to static list. */
>>>> +       for (n = 0; n < soft_event_info.pm_nevent; n++) {
>>>> +               soft_event_table[n].pm_ev_name =
>>>> +                   soft_event_info.pm_events[n].pm_ev_name;
>>>> +               soft_event_table[n].pm_ev_code =
>>>> +                   soft_event_info.pm_events[n].pm_ev_code;
>>>> +       }
>>>> +       soft_class_table_descr.pm_evc_event_table_size = \
>>>> +           soft_event_info.pm_nevent;
>>>> +       soft_class_table_descr.pm_evc_event_table = \
>>>> +           soft_event_table;
>>>> +
>>>> +       /*
>>>>         * Fill in the class table.
>>>>         */
>>>>        n = 0;
>>>> +
>>>> +       /* Fill soft events information. */
>>>> +       pmc_class_table[n++] = &soft_class_table_descr;
>>>>  #if defined(__amd64__) || defined(__i386__)
>>>> -       pmc_class_table[n++] = &tsc_class_table_descr;
>>>> +       if (cpu_info.pm_cputype != PMC_CPU_GENERIC)
>>>> +               pmc_class_table[n++] = &tsc_class_table_descr;
>>>>
>>>>        /*
>>>>         * Check if this CPU has fixed function counters.
>>>> @@ -2867,6 +2929,9 @@ pmc_init(void)
>>>>                pmc_class_table[n] = &p4_class_table_descr;
>>>>                break;
>>>>  #endif
>>>> +       case PMC_CPU_GENERIC:
>>>> +               PMC_MDEP_INIT(generic);
>>>> +               break;
>>>>  #if defined(__XSCALE__)
>>>>        case PMC_CPU_INTEL_XSCALE:
>>>>                PMC_MDEP_INIT(xscale);
>>>> @@ -3035,18 +3100,19 @@ _pmc_name_of_event(enum pmc_event pe, en
>>>>                evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale);
>>>>        } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) {
>>>>                ev = mips24k_event_table;
>>>> -               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k
>>>> -);
>>>> +               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k);
>>>>        } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) {
>>>>                ev = octeon_event_table;
>>>>                evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon);
>>>>        } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) {
>>>>                ev = ppc7450_event_table;
>>>> -               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450
>>>> -);
>>>> +               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450);
>>>>        } else if (pe == PMC_EV_TSC_TSC) {
>>>>                ev = tsc_event_table;
>>>>                evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
>>>> +       } else if (pe >= PMC_EV_SOFT_FIRST && pe <= PMC_EV_SOFT_LAST) {
>>>> +               ev = soft_event_table;
>>>> +               evfence = soft_event_table + soft_event_info.pm_nevent;
>>>>        }
>>>>
>>>>        for (; ev != evfence; ev++)
>>>>
>>>> Modified: head/lib/libpmc/pmc.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.3       Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.3       Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -223,6 +223,8 @@ and
>>>>  CPUs.
>>>>  .It Li PMC_CLASS_TSC
>>>>  The timestamp counter on i386 and amd64 architecture CPUs.
>>>> +.It Li PMC_CLASS_SOFT
>>>> +Software events.
>>>>  .El
>>>>  .Ss PMC Capabilities
>>>>  Capabilities of performance monitoring hardware are denoted using
>>>> @@ -525,6 +527,7 @@ API is
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmclog 3 ,
>>>>  .Xr hwpmc 4 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.atom.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -1176,6 +1176,7 @@ and the underlying hardware events used
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.core.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.core.3  Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.core.3  Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -792,6 +792,7 @@ may not count some transitions.
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmclog 3 ,
>>>>  .Xr hwpmc 4
>>>>
>>>> Modified: head/lib/libpmc/pmc.core2.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -1107,6 +1107,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.corei7.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -1559,6 +1559,7 @@ Counts number of segment register loads.
>>>>  .Xr pmc.corei7uc 3 ,
>>>>  .Xr pmc.westmere 3 ,
>>>>  .Xr pmc.westmereuc 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.corei7uc.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -863,6 +863,7 @@ refreshed or needs to go into a power do
>>>>  .Xr pmc.corei7 3 ,
>>>>  .Xr pmc.westmere 3 ,
>>>>  .Xr pmc.westmereuc 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.iaf.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -132,6 +132,7 @@ CPU, use the event specifier
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.k7.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -249,6 +249,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmclog 3 ,
>>>>  .Xr hwpmc 4
>>>>
>>>> Modified: head/lib/libpmc/pmc.k8.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -783,6 +783,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmclog 3 ,
>>>>  .Xr hwpmc 4
>>>>
>>>> Modified: head/lib/libpmc/pmc.mips24k.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -392,6 +392,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.octeon.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -232,6 +232,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.p4.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -1208,6 +1208,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc.k8 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmclog 3 ,
>>>>  .Xr hwpmc 4
>>>>
>>>> Modified: head/lib/libpmc/pmc.p5.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -444,6 +444,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc.k8 3 ,
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmclog 3 ,
>>>>  .Xr hwpmc 4
>>>>
>>>> Modified: head/lib/libpmc/pmc.p6.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -1010,6 +1010,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc.k8 3 ,
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmclog 3 ,
>>>>  .Xr hwpmc 4
>>>>
>>>> Modified: head/lib/libpmc/pmc.sandybridge.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -907,6 +907,7 @@ Split locks in SQ.
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>>  .Xr pmc.sandybridgeuc 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc.ucf 3 ,
>>>>  .Xr pmc.westmere 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.sandybridgeuc.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -208,6 +208,7 @@ Counts the number of core-outgoing entri
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>>  .Xr pmc.sandybridge 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc.ucf 3 ,
>>>>  .Xr pmc.westmere 3 ,
>>>>
>>>> Added: head/lib/libpmc/pmc.soft.3
>>>> ==============================================================================
>>>> --- /dev/null   00:00:00 1970   (empty, because file is newly added)
>>>> +++ head/lib/libpmc/pmc.soft.3  Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -0,0 +1,104 @@
>>>> +.\" Copyright (c) 2012 Fabien Thomas.  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$
>>>> +.\"
>>>> +.Dd March 28, 2012
>>>> +.Os
>>>> +.Dt PMC.SOFT 3
>>>> +.Sh NAME
>>>> +.Nm pmc.soft
>>>> +.Nd measurements using software based events
>>>> +.Sh LIBRARY
>>>> +.Lb libpmc
>>>> +.Sh SYNOPSIS
>>>> +.In pmc.h
>>>> +.Sh DESCRIPTION
>>>> +Software events are used to collect various source of software events.
>>>> +.Ss PMC Features
>>>> +16 sampling counters using software events based on various sources.
>>>> +These PMCs support the following capabilities:
>>>> +.Bl -column "PMC_CAP_INTERRUPT" "Support"
>>>> +.It Em Capability Ta Em Support
>>>> +.It PMC_CAP_CASCADE Ta \&No
>>>> +.It PMC_CAP_EDGE Ta \&No
>>>> +.It PMC_CAP_INTERRUPT Ta Yes
>>>> +.It PMC_CAP_INVERT Ta \&No
>>>> +.It PMC_CAP_READ Ta Yes
>>>> +.It PMC_CAP_PRECISE Ta \&No
>>>> +.It PMC_CAP_SYSTEM Ta Yes
>>>> +.It PMC_CAP_TAGGING Ta \&No
>>>> +.It PMC_CAP_THRESHOLD Ta \&No
>>>> +.It PMC_CAP_USER Ta Yes
>>>> +.It PMC_CAP_WRITE Ta Yes
>>>> +.El
>>>> +.Ss Event Qualifiers
>>>> +There is no supported event qualifier.
>>>> +.Pp
>>>> +The event specifiers supported by software are:
>>>> +.Bl -tag -width indent
>>>> +.It Li CLOCK.HARD
>>>> +Hard clock ticks.
>>>> +.It Li CLOCK.STAT
>>>> +Stat clock ticks.
>>>> +.It Li LOCK.FAILED
>>>> +Lock acquisition failed.
>>>> +.It Li PAGE_FAULT.ALL
>>>> +All page fault type.
>>>> +.It Li PAGE_FAULT.READ
>>>> +Read page fault.
>>>> +.It Li PAGE_FAULT.WRITE
>>>> +Write page fault.
>>>> +.El
>>>> +.Sh SEE ALSO
>>>> +.Xr pmc 3 ,
>>>> +.Xr pmc.atom 3 ,
>>>> +.Xr pmc.core 3 ,
>>>> +.Xr pmc.iaf 3 ,
>>>> +.Xr pmc.ucf 3 ,
>>>> +.Xr pmc.k7 3 ,
>>>> +.Xr pmc.k8 3 ,
>>>> +.Xr pmc.p4 3 ,
>>>> +.Xr pmc.p5 3 ,
>>>> +.Xr pmc.p6 3 ,
>>>> +.Xr pmc.corei7 3 ,
>>>> +.Xr pmc.corei7uc 3 ,
>>>> +.Xr pmc.westmereuc 3 ,
>>>> +.Xr pmc.tsc 3 ,
>>>> +.Xr pmc_cpuinfo 3 ,
>>>> +.Xr pmclog 3 ,
>>>> +.Xr hwpmc 4
>>>> +.Sh HISTORY
>>>> +The
>>>> +.Nm pmc
>>>> +library first appeared in
>>>> +.Fx 6.0 .
>>>> +.Sh AUTHORS
>>>> +The
>>>> +.Lb libpmc
>>>> +library was written by
>>>> +.An "Joseph Koshy"
>>>> +.Aq [hidden email] .
>>>> +Software PMC was written by
>>>> +.An "Fabien Thomas"
>>>> +.Aq [hidden email] .
>>>>
>>>> Modified: head/lib/libpmc/pmc.tsc.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -68,6 +68,7 @@ maps to the TSC.
>>>>  .Xr pmc.p4 3 ,
>>>>  .Xr pmc.p5 3 ,
>>>>  .Xr pmc.p6 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmclog 3 ,
>>>>  .Xr hwpmc 4
>>>>  .Sh HISTORY
>>>>
>>>> Modified: head/lib/libpmc/pmc.ucf.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -96,6 +96,7 @@ offset C0H under device number 0 and Fun
>>>>  .Xr pmc.corei7uc 3 ,
>>>>  .Xr pmc.westmere 3 ,
>>>>  .Xr pmc.westmereuc 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.westmere.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -1381,6 +1381,7 @@ Counts number of SID integer 64 bit shif
>>>>  .Xr pmc.corei7 3 ,
>>>>  .Xr pmc.corei7uc 3 ,
>>>>  .Xr pmc.westmereuc 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.westmereuc.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -1066,6 +1066,7 @@ disabled.
>>>>  .Xr pmc.corei7 3 ,
>>>>  .Xr pmc.corei7uc 3 ,
>>>>  .Xr pmc.westmere 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr pmc.tsc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>>
>>>> Modified: head/lib/libpmc/pmc.xscale.3
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -134,6 +134,7 @@ and the underlying hardware events used.
>>>>  .Xr pmc 3 ,
>>>>  .Xr pmc_cpuinfo 3 ,
>>>>  .Xr pmclog 3 ,
>>>> +.Xr pmc.soft 3 ,
>>>>  .Xr hwpmc 4
>>>>  .Sh HISTORY
>>>>  The
>>>>
>>>> Modified: head/lib/libpmc/pmclog.c
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmclog.c    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmclog.c    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -369,6 +369,12 @@ pmclog_get_event(void *cookie, char **da
>>>>                    == NULL)
>>>>                        goto error;
>>>>                break;
>>>> +       case PMCLOG_TYPE_PMCALLOCATEDYN:
>>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_pmcid);
>>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_event);
>>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_flags);
>>>> +               PMCLOG_READSTRING(le,ev->pl_u.pl_ad.pl_evname,PMC_NAME_MAX);
>>>> +               break;
>>>>        case PMCLOG_TYPE_PMCATTACH:
>>>>                PMCLOG_GET_PATHLEN(pathlen,evlen,pmclog_pmcattach);
>>>>                PMCLOG_READ32(le,ev->pl_u.pl_t.pl_pmcid);
>>>>
>>>> Modified: head/lib/libpmc/pmclog.h
>>>> ==============================================================================
>>>> --- head/lib/libpmc/pmclog.h    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/lib/libpmc/pmclog.h    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -88,6 +88,13 @@ struct pmclog_ev_pmcallocate {
>>>>        pmc_id_t        pl_pmcid;
>>>>  };
>>>>
>>>> +struct pmclog_ev_pmcallocatedyn {
>>>> +       uint32_t        pl_event;
>>>> +       char            pl_evname[PMC_NAME_MAX];
>>>> +       uint32_t        pl_flags;
>>>> +       pmc_id_t        pl_pmcid;
>>>> +};
>>>> +
>>>>  struct pmclog_ev_pmcattach {
>>>>        pmc_id_t        pl_pmcid;
>>>>        pid_t           pl_pid;
>>>> @@ -146,6 +153,7 @@ struct pmclog_ev {
>>>>                struct pmclog_ev_map_out        pl_mo;
>>>>                struct pmclog_ev_pcsample       pl_s;
>>>>                struct pmclog_ev_pmcallocate    pl_a;
>>>> +               struct pmclog_ev_pmcallocatedyn pl_ad;
>>>>                struct pmclog_ev_pmcattach      pl_t;
>>>>                struct pmclog_ev_pmcdetach      pl_d;
>>>>                struct pmclog_ev_proccsw        pl_c;
>>>>
>>>> Modified: head/sys/amd64/amd64/trap.c
>>>> ==============================================================================
>>>> --- head/sys/amd64/amd64/trap.c Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/amd64/amd64/trap.c Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
>>>>  #include <sys/vmmeter.h>
>>>>  #ifdef HWPMC_HOOKS
>>>>  #include <sys/pmckern.h>
>>>> +PMC_SOFT_DEFINE( , , page_fault, all);
>>>> +PMC_SOFT_DEFINE( , , page_fault, read);
>>>> +PMC_SOFT_DEFINE( , , page_fault, write);
>>>>  #endif
>>>>
>>>>  #include <vm/vm.h>
>>>> @@ -743,8 +746,20 @@ trap_pfault(frame, usermode)
>>>>                 */
>>>>                rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
>>>>        }
>>>> -       if (rv == KERN_SUCCESS)
>>>> +       if (rv == KERN_SUCCESS) {
>>>> +#ifdef HWPMC_HOOKS
>>>> +               if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
>>>> +                       PMC_SOFT_CALL_TF( , , page_fault, all, frame);
>>>> +                       if (ftype == VM_PROT_READ)
>>>> +                               PMC_SOFT_CALL_TF( , , page_fault, read,
>>>> +                                   frame);
>>>> +                       else
>>>> +                               PMC_SOFT_CALL_TF( , , page_fault, write,
>>>> +                                   frame);
>>>> +               }
>>>> +#endif
>>>>                return (0);
>>>> +       }
>>>>  nogo:
>>>>        if (!usermode) {
>>>>                if (td->td_intr_nesting_level == 0 &&
>>>>
>>>> Modified: head/sys/amd64/include/pmc_mdep.h
>>>> ==============================================================================
>>>> --- head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -50,13 +50,13 @@ struct pmc_mdep;
>>>>  * measurement architecture have PMCs of the following classes: TSC,
>>>>  * IAF, IAP, UCF and UCP.
>>>>  */
>>>> -#define        PMC_MDEP_CLASS_INDEX_TSC        0
>>>> -#define        PMC_MDEP_CLASS_INDEX_K8         1
>>>> -#define        PMC_MDEP_CLASS_INDEX_P4         1
>>>> -#define        PMC_MDEP_CLASS_INDEX_IAP        1
>>>> -#define        PMC_MDEP_CLASS_INDEX_IAF        2
>>>> -#define        PMC_MDEP_CLASS_INDEX_UCP        3
>>>> -#define        PMC_MDEP_CLASS_INDEX_UCF        4
>>>> +#define        PMC_MDEP_CLASS_INDEX_TSC        1
>>>> +#define        PMC_MDEP_CLASS_INDEX_K8         2
>>>> +#define        PMC_MDEP_CLASS_INDEX_P4         2
>>>> +#define        PMC_MDEP_CLASS_INDEX_IAP        2
>>>> +#define        PMC_MDEP_CLASS_INDEX_IAF        3
>>>> +#define        PMC_MDEP_CLASS_INDEX_UCP        4
>>>> +#define        PMC_MDEP_CLASS_INDEX_UCF        5
>>>>
>>>>  /*
>>>>  * On the amd64 platform we support the following PMCs.
>>>> @@ -119,6 +119,15 @@ union pmc_md_pmc {
>>>>
>>>>  #define        PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
>>>>
>>>> +/* Build a fake kernel trapframe from current instruction pointer. */
>>>> +#define PMC_FAKE_TRAPFRAME(TF)                                         \
>>>> +       do {                                                            \
>>>> +       (TF)->tf_cs = 0; (TF)->tf_rflags = 0;                           \
>>>> +       __asm __volatile("movq %%rbp,%0" : "=r" ((TF)->tf_rbp));        \
>>>> +       __asm __volatile("movq %%rsp,%0" : "=r" ((TF)->tf_rsp));        \
>>>> +       __asm __volatile("call 1f \n\t1: pop %0" : "=r"((TF)->tf_rip)); \
>>>> +       } while (0)
>>>> +
>>>>  /*
>>>>  * Prototypes
>>>>  */
>>>>
>>>> Modified: head/sys/arm/include/pmc_mdep.h
>>>> ==============================================================================
>>>> --- head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -29,7 +29,7 @@
>>>>  #ifndef _MACHINE_PMC_MDEP_H_
>>>>  #define        _MACHINE_PMC_MDEP_H_
>>>>
>>>> -#define        PMC_MDEP_CLASS_INDEX_XSCALE     0
>>>> +#define        PMC_MDEP_CLASS_INDEX_XSCALE     1
>>>>  /*
>>>>  * On the ARM platform we support the following PMCs.
>>>>  *
>>>>
>>>> Modified: head/sys/conf/files
>>>> ==============================================================================
>>>> --- head/sys/conf/files Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/conf/files Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -1260,6 +1260,7 @@ dev/hme/if_hme_sbus.c             optional hme sbus
>>>>  dev/hptiop/hptiop.c            optional hptiop scbus
>>>>  dev/hwpmc/hwpmc_logging.c      optional hwpmc
>>>>  dev/hwpmc/hwpmc_mod.c          optional hwpmc
>>>> +dev/hwpmc/hwpmc_soft.c         optional hwpmc
>>>>  dev/ichsmb/ichsmb.c            optional ichsmb
>>>>  dev/ichsmb/ichsmb_pci.c                optional ichsmb pci
>>>>  dev/ida/ida.c                  optional ida
>>>>
>>>> Modified: head/sys/dev/hwpmc/hwpmc_amd.c
>>>> ==============================================================================
>>>> --- head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -687,7 +687,8 @@ amd_intr(int cpu, struct trapframe *tf)
>>>>                wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
>>>>
>>>>                /* Restart the counter if logging succeeded. */
>>>> -               error = pmc_process_interrupt(cpu, pm, tf, TRAPF_USERMODE(tf));
>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>> +                   TRAPF_USERMODE(tf));
>>>>                if (error == 0)
>>>>                        wrmsr(evsel, config | AMD_PMC_ENABLE);
>>>>        }
>>>> @@ -874,7 +875,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int c
>>>>  struct pmc_mdep *
>>>>  pmc_amd_initialize(void)
>>>>  {
>>>> -       int classindex, error, i, nclasses, ncpus;
>>>> +       int classindex, error, i, ncpus;
>>>>        struct pmc_classdep *pcd;
>>>>        enum pmc_cputype cputype;
>>>>        struct pmc_mdep *pmc_mdep;
>>>> @@ -926,12 +927,9 @@ pmc_amd_initialize(void)
>>>>         * These processors have two classes of PMCs: the TSC and
>>>>         * programmable PMCs.
>>>>         */
>>>> -       nclasses = 2;
>>>> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses * sizeof (struct pmc_classdep),
>>>> -           M_PMC, M_WAITOK|M_ZERO);
>>>> +       pmc_mdep = pmc_mdep_alloc(2);
>>>>
>>>>        pmc_mdep->pmd_cputype = cputype;
>>>> -       pmc_mdep->pmd_nclass  = nclasses;
>>>>
>>>>        ncpus = pmc_cpu_max();
>>>>
>>>>
>>>> Modified: head/sys/dev/hwpmc/hwpmc_core.c
>>>> ==============================================================================
>>>> --- head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -2239,7 +2239,7 @@ core_intr(int cpu, struct trapframe *tf)
>>>>                if (pm->pm_state != PMC_STATE_RUNNING)
>>>>                        continue;
>>>>
>>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>                    TRAPF_USERMODE(tf));
>>>>
>>>>                v = pm->pm_sc.pm_reloadcount;
>>>> @@ -2326,7 +2326,7 @@ core2_intr(int cpu, struct trapframe *tf
>>>>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>>>>                        continue;
>>>>
>>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>                    TRAPF_USERMODE(tf));
>>>>                if (error)
>>>>                        intrenable &= ~flag;
>>>> @@ -2354,7 +2354,7 @@ core2_intr(int cpu, struct trapframe *tf
>>>>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>>>>                        continue;
>>>>
>>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>                    TRAPF_USERMODE(tf));
>>>>                if (error)
>>>>                        intrenable &= ~flag;
>>>>
>>>> Modified: head/sys/dev/hwpmc/hwpmc_intel.c
>>>> ==============================================================================
>>>> --- head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -162,12 +162,10 @@ pmc_intel_initialize(void)
>>>>                return (NULL);
>>>>        }
>>>>
>>>> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses *
>>>> -           sizeof(struct pmc_classdep), M_PMC, M_WAITOK|M_ZERO);
>>>> +       /* Allocate base class and initialize machine dependent struct */
>>>> +       pmc_mdep = pmc_mdep_alloc(nclasses);
>>>>
>>>>        pmc_mdep->pmd_cputype    = cputype;
>>>> -       pmc_mdep->pmd_nclass     = nclasses;
>>>> -
>>>>        pmc_mdep->pmd_switch_in  = intel_switch_in;
>>>>        pmc_mdep->pmd_switch_out = intel_switch_out;
>>>>
>>>>
>>>> Modified: head/sys/dev/hwpmc/hwpmc_logging.c
>>>> ==============================================================================
>>>> --- head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -129,6 +129,7 @@ static struct mtx pmc_kthread_mtx;  /* sl
>>>>
>>>>  /* Emit a string.  Caution: does NOT update _le, so needs to be last */
>>>>  #define        PMCLOG_EMITSTRING(S,L)  do { bcopy((S), _le, (L)); } while (0)
>>>> +#define        PMCLOG_EMITNULLSTRING(L) do { bzero(_le, (L)); } while (0)
>>>>
>>>>  #define        PMCLOG_DESPATCH(PO)                                             \
>>>>                pmclog_release((PO));                                   \
>>>> @@ -835,16 +836,33 @@ void
>>>>  pmclog_process_pmcallocate(struct pmc *pm)
>>>>  {
>>>>        struct pmc_owner *po;
>>>> +       struct pmc_soft *ps;
>>>>
>>>>        po = pm->pm_owner;
>>>>
>>>>        PMCDBG(LOG,ALL,1, "pm=%p", pm);
>>>>
>>>> -       PMCLOG_RESERVE(po, PMCALLOCATE, sizeof(struct pmclog_pmcallocate));
>>>> -       PMCLOG_EMIT32(pm->pm_id);
>>>> -       PMCLOG_EMIT32(pm->pm_event);
>>>> -       PMCLOG_EMIT32(pm->pm_flags);
>>>> -       PMCLOG_DESPATCH(po);
>>>> +       if (PMC_TO_CLASS(pm) == PMC_CLASS_SOFT) {
>>>> +               PMCLOG_RESERVE(po, PMCALLOCATEDYN,
>>>> +                   sizeof(struct pmclog_pmcallocatedyn));
>>>> +               PMCLOG_EMIT32(pm->pm_id);
>>>> +               PMCLOG_EMIT32(pm->pm_event);
>>>> +               PMCLOG_EMIT32(pm->pm_flags);
>>>> +               ps = pmc_soft_ev_acquire(pm->pm_event);
>>>> +               if (ps != NULL)
>>>> +                       PMCLOG_EMITSTRING(ps->ps_ev.pm_ev_name,PMC_NAME_MAX);
>>>> +               else
>>>> +                       PMCLOG_EMITNULLSTRING(PMC_NAME_MAX);
>>>> +               pmc_soft_ev_release(ps);
>>>> +               PMCLOG_DESPATCH(po);
>>>> +       } else {
>>>> +               PMCLOG_RESERVE(po, PMCALLOCATE,
>>>> +                   sizeof(struct pmclog_pmcallocate));
>>>> +               PMCLOG_EMIT32(pm->pm_id);
>>>> +               PMCLOG_EMIT32(pm->pm_event);
>>>> +               PMCLOG_EMIT32(pm->pm_flags);
>>>> +               PMCLOG_DESPATCH(po);
>>>> +       }
>>>>  }
>>>>
>>>>  void
>>>>
>>>> Modified: head/sys/dev/hwpmc/hwpmc_mips.c
>>>> ==============================================================================
>>>> --- head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -287,7 +287,7 @@ mips_pmc_intr(int cpu, struct trapframe
>>>>                retval = 1;
>>>>                if (pm->pm_state != PMC_STATE_RUNNING)
>>>>                        continue;
>>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>                    TRAPF_USERMODE(tf));
>>>>                if (error) {
>>>>                        /* Clear/disable the relevant counter */
>>>>
>>>> Modified: head/sys/dev/hwpmc/hwpmc_mod.c
>>>> ==============================================================================
>>>> --- head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:49:11 2012        (r233627)
>>>> +++ head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:58:30 2012        (r233628)
>>>> @@ -70,6 +70,8 @@ __FBSDID("$FreeBSD$");
>>>>  #include <vm/vm_map.h>
>>>>  #include <vm/vm_object.h>
>>>>
>>>> +#include "hwpmc_soft.h"
>>>> +
>>>>  /*
>>>>  * Types
>>>>  */
>>>> @@ -182,7 +184,7 @@ static int  pmc_attach_one_process(struct
>>>>  static int     pmc_can_allocate_rowindex(struct proc *p, unsigned int ri,
>>>>     int cpu);
>>>>  static int     pmc_can_attach(struct pmc *pm, struct proc *p);
>>>> -static void    pmc_capture_user_callchain(int cpu, struct trapframe *tf);
>>>> +static void    pmc_capture_user_callchain(int cpu, int soft, struct trapframe *tf);
>>>>  static void    pmc_cleanup(void);
>>>>  static int     pmc_detach_process(struct proc *p, struct pmc *pm);
>>>>  static int     pmc_detach_one_process(struct proc *p, struct pmc *pm,
>>>> @@ -206,7 +208,7 @@ static void pmc_process_csw_out(struct t
>>>>  static void    pmc_process_exit(void *arg, struct proc *p);
>>>>  static void    pmc_process_fork(void *arg, struct proc *p1,
>>>>     struct proc *p2, int n);
>>>> -static void    pmc_process_samples(int cpu);
>>>> +static void    pmc_process_samples(int cpu, int soft);
>>>>  static void    pmc_release_pmc_descriptor(struct pmc *pmc);
>>>>  static void    pmc_remove_owner(struct pmc_owner *po);
>>>>  static void    pmc_remove_process_descriptor(struct pmc_process *pp);
>>>> @@ -218,12 +220,16 @@ static int        pmc_stop(struct pmc *pm);
>>>>  static int     pmc_syscall_handler(struct thread *td, void *syscall_args);
>>>>  static void    pmc_unlink_target_process(struct pmc *pmc,
>>>>     struct pmc_process *pp);
>>>> +static int generic_switch_in(struct pmc_cpu *pc, struct pmc_process *pp);
>>>> +static int generic_switch_out(struct pmc_cpu *pc, struct pmc_process *pp);
>>>> +static struct pmc_mdep *pmc_generic_cpu_initialize(void);
>>>> +static void pmc_generic_cpu_finalize(struct pmc_mdep *md);
>>>>
>>>>  /*
>>>>  * Kernel tunables and sysctl(8) interface.
>>>>  */
>>>>
>>>> -SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0, "HWPMC parameters");
>>>> +SYSCTL_DECL(_kern_hwpmc);
>>>>
>>>>  static int pmc_callchaindepth = PMC_CALLCHAIN_DEPTH;
>>>>  TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "callchaindepth", &pmc_callchaindepth);
>>>> @@ -1833,7 +1839,9 @@ const char *pmc_hooknames[] = {
>>>>        "KLDUNLOAD",
>>>>        "MMAP",
>>>>        "MUNMAP",
>>>> -       "CALLCHAIN"
>>>> +       "CALLCHAIN-NMI",
>>>> +       "CALLCHAIN-SOFT",
>>>> +       "SOFTSAMPLING"
>>>>  };
>>>>  #endif
>>>>
>>>> @@ -1992,7 +2000,8 @@ pmc_hook_handler(struct thread *td, int
>>>>                 * lose the interrupt sample.
>>>>                 */
>>>>                CPU_CLR_ATOMIC(PCPU_GET(cpuid), &pmc_cpumask);
>>>> -               pmc_process_samples(PCPU_GET(cpuid));
>>>> +               pmc_process_samples(PCPU_GET(cpuid), PMC_HR);
>>>> +               pmc_process_samples(PCPU_GET(cpuid), PMC_SR);
>>>>                break;
>>>>
>>>>
>>>> @@ -2022,11 +2031,30 @@ pmc_hook_handler(struct thread *td, int
>>>>                 */
>>>>                KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>>>>                    __LINE__));
>>>> -               pmc_capture_user_callchain(PCPU_GET(cpuid),
>>>> +
>>>> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_HR,
>>>>                    (struct trapframe *) arg);
>>>>                td->td_pflags &= ~TDP_CALLCHAIN;
>>>>                break;
>>>>
>>>> +       case PMC_FN_USER_CALLCHAIN_SOFT:
>>>> +               /*
>>>> +                * Record a call chain.
>>>> +                */
>>>> +               KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>>>> +                   __LINE__));
>>>> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_SR,
>>>> +                   (struct trapframe *) arg);
>>>> +               td->td_pflags &= ~TDP_CALLCHAIN;
>>>> +               break;
>>>> +
>>>> +       case PMC_FN_SOFT_SAMPLING:
>>>> +               /*
>>>> +                * Call soft PMC sampling intr.
>>>> +                */
>>>> +               pmc_soft_intr((struct pmckern_soft *) arg);
>>>> +               break;
>>>> +
>>>>        default:
>>>>  #ifdef DEBUG
>>>>                KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
>>>> @@ -2221,18 +2249,17 @@ pmc_destroy_pmc_descriptor(struct pmc *p
>>>>  static void
>>>>  pmc_wait_for_pmc_idle(struct pmc *pm)
>>>>  {
>>>> -#ifdef DEBUG
>>>> +#ifdef DEBUG
>>>>        volatile int maxloop;
>>>>
>>>>        maxloop = 100 * pmc_cpu_max();
>>>>  #endif
>>>> -
>>>>        /*
>>>>         * Loop (with a forced context switch) till the PMC's runcount
>>>>         * comes down to zero.
>>>>         */
>>>>        while (atomic_load_acq_32(&pm->pm_runcount) > 0) {
>>>> -#ifdef DEBUG
>>>> +#ifdef DEBUG
>>>>                maxloop--;
>>>>                KASSERT(maxloop > 0,
>>>>                    ("[pmc,%d] (ri%d, rc%d) waiting too long for "
>>>> @@ -2972,6 +2999,53 @@ pmc_syscall_handler(struct thread *td, v
>>>>        }
>>>>        break;
>>>>
>>>> +       /*
>>>> +        * Retrieve soft events list.
>>>> +        */
>>>> +       case PMC_OP_GETDYNEVENTINFO:
>>>> +       {
>>>> +               enum pmc_class                  cl;
>>>> +               enum pmc_event                  ev;
>>>> +               struct pmc_op_getdyneventinfo   *gei;
>>>> +               struct pmc_dyn_event_descr      dev;
>>>> +               struct pmc_soft                 *ps;
>>>> +               uint32_t                        nevent;
>>>> +
>>>> +               sx_assert(&pmc_sx, SX_LOCKED);
>>>> +
>>>> +               gei = (struct pmc_op_getdyneventinfo *) arg;
>>>> +
>>>> +               if ((error = copyin(&gei->pm_class, &cl, sizeof(cl))) != 0)
>>>> +                       break;
>>>> +
>>>> +               /* Only SOFT class is dynamic. */
>>>> +               if (cl != PMC_CLASS_SOFT) {
>>>> +                       error = EINVAL;
>>>> +                       break;
>>>> +               }
>>>> +
>>>> +               nevent = 0;
>>>> +               for (ev = PMC_EV_SOFT_FIRST; ev <= PMC_EV_SOFT_LAST; ev++) {
>>>> +                       ps = pmc_soft_ev_acquire(ev);
>>>> +                       if (ps == NULL)
>>>> +                               continue;
>>>> +                       bcopy(&ps->ps_ev, &dev, sizeof(dev));
>>>> +                       pmc_soft_ev_release(ps);
>>>> +
>>>> +                       error = copyout(&dev,
>>>> +                           &gei->pm_events[nevent],
>>>> +                           sizeof(struct pmc_dyn_event_descr));
>>>> +                       if (error != 0)
>>>> +                               break;
>>>> +                       nevent++;
>>>> +               }
>>>> +               if (error != 0)
>>>> +                       break;
>>>> +
>>>> +               error = copyout(&nevent, &gei->pm_nevent,
>>>>
>>>> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
>>
>>
>>
>> --
>> Monthadar Al Jaberi
>> <RSPRO_USB_PROD>
>
>



--
Monthadar Al Jaberi
_______________________________________________
[hidden email] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-mips
To unsubscribe, send any mail to "[hidden email]"
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: svn commit: r233628 - in head: lib/libpmc sys/amd64/amd64 sys/amd64/include sys/arm/include sys/conf sys/dev/hwpmc sys/i386/i386 sys/i386/include sys/kern sys/mips/include sys/modules/hwpmc sys/pow...

Fabien THOMAS

Le 23 avr. 2012 à 10:06, Monthadar Al Jaberi a écrit :

> On Mon, Apr 23, 2012 at 9:47 AM, Fabien Thomas <[hidden email]> wrote:
>> Hi,
>>
>> The rumors seems true :)
>> Can you try the patch attached (I cannot test as i've no MIPS hardware) ?
>
> my RSPRO boots fine now, thank you :)
>
commited as r234598.
Thanks!

>>
>> Thanks,
>> Fabien
>>
>>
>>> On Mon, Apr 23, 2012 at 8:44 AM, Adrian Chadd <[hidden email]> wrote:
>>>> Hi Fabien,
>>>>
>>>> I've heard some rumours that this broke hwpmc support for mips24k.
>>>>
>>>> Monthadar, can you please provide some background info for this?
>>>>
>>>
>>> This is the log output
>>>
>>> Using default protocol (TFTP)
>>> Entry point: 0x80050100, address range: 0x80050000-0x804f1dcc
>>> RedBoot> exec
>>> Now booting linux kernel:
>>> Base address 0x80050000 Entry 0x80050100
>>> memsize=0x08000000
>>> modetty0=0,n,8,1,hw
>>> board=RouterStation PRO
>>> ethaddr=00.15.6d.c8.c9.2e
>>> CPU platform: Atheros AR7161 rev 2
>>> CPU Frequency=720 MHz
>>> CPU DDR Frequency=360 MHz
>>> CPU AHB Frequency=180 MHz
>>> platform frequency: 720000000
>>> arguments:
>>>  a0 = 00000002
>>>  a1 = 80050028
>>>  a2 = 80050000
>>>  a3 = 00000001
>>> Cmd line:  �������m���������������_}������߾q��������������� �����������������߿���������_�w���� �����?-����{������~��
>>> Environment:
>>>  memsize = 0x08000000
>>>  modetty0 = 0,n,8,1,hw
>>>  ethaddr = 00.15.6d.c8.c9.2e
>>>  board = RouterStation PRO
>>> Cache info:
>>>  picache_stride    = 4096
>>>  picache_loopcount = 16
>>>  pdcache_stride    = 4096
>>>  pdcache_loopcount = 8
>>> cpu0: MIPS Technologies processor v116.147
>>>  MMU: Standard TLB, 16 entries
>>>  L1 i-cache: 4 ways of 512 sets, 32 bytes per line
>>>  L1 d-cache: 4 ways of 256 sets, 32 bytes per line
>>>  Config1=0x9ee3519e<PerfCount,WatchRegs,MIPS16,EJTAG>
>>>  Config3=0x20
>>> KDB: debugger backends: ddb
>>> KDB: current backend: ddb
>>> Copyright (c) 1992-2012 The FreeBSD Project.
>>> Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
>>>       The Regents of the University of California. All rights reserved.
>>> FreeBSD is a registered trademark of The FreeBSD Foundation.
>>> FreeBSD 10.0-CURRENT #12: Fri Apr 20 18:03:16 CEST 2012
>>>    root@freebsd-re-9:/usr/obj/mips.mips/usr/src/sys/RSPRO_USB_PROD mips
>>> WARNING: WITNESS option enabled, expect reduced performance.
>>> MEMGUARD DEBUGGING ALLOCATOR INITIALIZED:
>>>       MEMGUARD map base: 0xc0800000
>>>       MEMGUARD map limit: 0xc1c00000
>>>       MEMGUARD map size: 20480 KBytes
>>> real memory  = 134217728 (131072K bytes)
>>> avail memory = 123117568 (117MB)
>>> random device not loaded; using insecure entropy
>>> nexus0: <MIPS32 root nexus>
>>> clock0: <Generic MIPS32 ticker> on nexus0
>>> Timecounter "MIPS32" frequency 360000000 Hz quality 800
>>> Event timer "MIPS32" frequency 360000000 Hz quality 800
>>> apb0 at irq 4 on nexus0
>>> uart0: <16550 or compatible> on apb0
>>> uart0: console (115200,n,8,1)
>>> gpio0: <Atheros AR71XX GPIO driver> on apb0
>>> gpio0: [GIANT-LOCKED]
>>> gpio0: gpio pinmask=0x0
>>> gpioc0: <GPIO controller> on gpio0
>>> gpiobus0: <GPIO bus> on gpio0
>>> ehci0: <AR71XX Integrated USB 2.0 controller> at mem
>>> 0x1b000000-0x1bffffff irq 1 on nexus0
>>> usbus0: set host controller mode
>>> usbus0: EHCI version 1.0
>>> usbus0: set host controller mode
>>> usbus0 on ehci0
>>> pcib0 at irq 0 on nexus0
>>> pci0: <PCI bus> on pcib0
>>> pci0: <old, non-VGA display device> at device 0.0 (no driver attached)
>>> ath0: <Atheros 5413> irq 0 at device 17.0 on pci0
>>> ath0: AR5413 mac 10.5 RF5413 phy 6.1
>>> ath0: 2GHz radio: 0x0000; 5GHz radio: 0x0063
>>> arge0: <Atheros AR71xx built-in ethernet interface> at mem
>>> 0x19000000-0x19000fff irq 2 on nexus0
>>> arge0: No PHY specified, using mask 16
>>> miibus0: <MII bus> on arge0
>>> ukphy0: <Generic IEEE 802.3u media interface> PHY 4 on miibus0
>>> ukphy0:  none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX,
>>> 1000baseT-FDX, 1000baseT-FDX-master, auto
>>> arge0: Ethernet address: 00:15:6d:c8:c9:2e
>>> arge1: <Atheros AR71xx built-in ethernet interface> at mem
>>> 0x1a000000-0x1a000fff irq 3 on nexus0
>>> arge1: No PHY specified, using mask 15
>>> arge1: Ethernet address: 00:15:6d:c8:c9:2f
>>> spi0: <AR71XX SPI> at mem 0x1f000000-0x1f00000f on nexus0
>>> spibus0: <spibus bus> on spi0
>>> mx25l0: <M25Pxx Flash Family> at cs 0 on spibus0
>>> mx25l0: mx25ll128, sector 65536 bytes, 256 sectors
>>> ar71xx_wdog0: <Atheros AR71XX watchdog timer> on nexus0
>>> Timecounters tick every 1.000 msec
>>> usbus0: 480Mbps High Speed USB v2.0
>>> ugen0.1: <Atheros> at usbus0
>>> uhub0: <Atheros EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus0
>>> panic: [pmc,4816] npmc miscomputed: ri=0, md->npmc=2
>>> KDB: enter: panic
>>> [ thread pid 0 tid 100000 ]
>>> Stopped at      kdb_enter+0x4c: lui     at,0x8050
>>> db> tr
>>> Tracing pid 0 tid 100000 td 0x804f76d0
>>> db_trace_thread+30 (?,?,?,?) ra 8068b94800000018 sp 0 sz 0
>>> 80075adc+114 (0,?,ffffffff,?) ra 8068b96000000020 sp 100000000 sz 1
>>> 80074e24+388 (?,?,?,?) ra 8068b980000000a8 sp 0 sz 0
>>> db_command_loop+70 (?,?,?,?) ra 8068ba2800000018 sp 0 sz 0
>>> 80077900+f4 (?,?,?,?) ra 8068ba40000001a8 sp 0 sz 0
>>> kdb_trap+110 (?,?,?,?) ra 8068bbe800000030 sp 0 sz 0
>>> trap+c7c (?,?,?,?) ra 8068bc18000000b8 sp 0 sz 0
>>> MipsKernGenException+134 (0,4,8043b1d4,119) ra 8068bcd0000000c8 sp
>>> 100000001 sz 1
>>> kdb_enter+4c (?,?,?,?) ra 8068bd9800000018 sp 0 sz 0
>>> panic+11c (?,12d0,0,2) ra 8068bdb000000028 sp 1 sz 1
>>> 800e8ca8+274 (?,?,?,?) ra 8068bdd800000038 sp 0 sz 0
>>> syscall_module_handler+b8 (?,?,?,?) ra 8068be1000000028 sp 0 sz 0
>>> module_register_init+9c (?,?,?,?) ra 8068be3800000028 sp 0 sz 0
>>> mi_startup+138 (?,?,?,?) ra 8068be6000000020 sp 0 sz 0
>>> _start+90 (?,?,?,?) ra 8068be8000000000 sp 0 sz 0
>>> pid 0
>>> db>
>>>
>>>> Thanks,
>>>>
>>>>
>>>>
>>>> adrian
>>>>
>>>> On 28 March 2012 13:58, Fabien Thomas <[hidden email]> wrote:
>>>>> Author: fabient
>>>>> Date: Wed Mar 28 20:58:30 2012
>>>>> New Revision: 233628
>>>>> URL: http://svn.freebsd.org/changeset/base/233628
>>>>>
>>>>> Log:
>>>>>  Add software PMC support.
>>>>>
>>>>>  New kernel events can be added at various location for sampling or counting.
>>>>>  This will for example allow easy system profiling whatever the processor is
>>>>>  with known tools like pmcstat(8).
>>>>>
>>>>>  Simultaneous usage of software PMC and hardware PMC is possible, for example
>>>>>  looking at the lock acquire failure, page fault while sampling on
>>>>>  instructions.
>>>>>
>>>>>  Sponsored by: NETASQ
>>>>>  MFC after:    1 month
>>>>>
>>>>> Added:
>>>>>  head/lib/libpmc/pmc.soft.3   (contents, props changed)
>>>>>  head/sys/dev/hwpmc/hwpmc_soft.c   (contents, props changed)
>>>>>  head/sys/dev/hwpmc/hwpmc_soft.h   (contents, props changed)
>>>>> Modified:
>>>>>  head/lib/libpmc/Makefile
>>>>>  head/lib/libpmc/libpmc.c
>>>>>  head/lib/libpmc/pmc.3
>>>>>  head/lib/libpmc/pmc.atom.3
>>>>>  head/lib/libpmc/pmc.core.3
>>>>>  head/lib/libpmc/pmc.core2.3
>>>>>  head/lib/libpmc/pmc.corei7.3
>>>>>  head/lib/libpmc/pmc.corei7uc.3
>>>>>  head/lib/libpmc/pmc.iaf.3
>>>>>  head/lib/libpmc/pmc.k7.3
>>>>>  head/lib/libpmc/pmc.k8.3
>>>>>  head/lib/libpmc/pmc.mips24k.3
>>>>>  head/lib/libpmc/pmc.octeon.3
>>>>>  head/lib/libpmc/pmc.p4.3
>>>>>  head/lib/libpmc/pmc.p5.3
>>>>>  head/lib/libpmc/pmc.p6.3
>>>>>  head/lib/libpmc/pmc.sandybridge.3
>>>>>  head/lib/libpmc/pmc.sandybridgeuc.3
>>>>>  head/lib/libpmc/pmc.tsc.3
>>>>>  head/lib/libpmc/pmc.ucf.3
>>>>>  head/lib/libpmc/pmc.westmere.3
>>>>>  head/lib/libpmc/pmc.westmereuc.3
>>>>>  head/lib/libpmc/pmc.xscale.3
>>>>>  head/lib/libpmc/pmclog.c
>>>>>  head/lib/libpmc/pmclog.h
>>>>>  head/sys/amd64/amd64/trap.c
>>>>>  head/sys/amd64/include/pmc_mdep.h
>>>>>  head/sys/arm/include/pmc_mdep.h
>>>>>  head/sys/conf/files
>>>>>  head/sys/dev/hwpmc/hwpmc_amd.c
>>>>>  head/sys/dev/hwpmc/hwpmc_core.c
>>>>>  head/sys/dev/hwpmc/hwpmc_intel.c
>>>>>  head/sys/dev/hwpmc/hwpmc_logging.c
>>>>>  head/sys/dev/hwpmc/hwpmc_mips.c
>>>>>  head/sys/dev/hwpmc/hwpmc_mod.c
>>>>>  head/sys/dev/hwpmc/hwpmc_piv.c
>>>>>  head/sys/dev/hwpmc/hwpmc_powerpc.c
>>>>>  head/sys/dev/hwpmc/hwpmc_ppro.c
>>>>>  head/sys/dev/hwpmc/hwpmc_tsc.c
>>>>>  head/sys/dev/hwpmc/hwpmc_x86.c
>>>>>  head/sys/dev/hwpmc/hwpmc_xscale.c
>>>>>  head/sys/dev/hwpmc/pmc_events.h
>>>>>  head/sys/i386/i386/trap.c
>>>>>  head/sys/i386/include/pmc_mdep.h
>>>>>  head/sys/kern/kern_clock.c
>>>>>  head/sys/kern/kern_lock.c
>>>>>  head/sys/kern/kern_mutex.c
>>>>>  head/sys/kern/kern_pmc.c
>>>>>  head/sys/kern/kern_rwlock.c
>>>>>  head/sys/kern/kern_sx.c
>>>>>  head/sys/kern/subr_trap.c
>>>>>  head/sys/mips/include/pmc_mdep.h
>>>>>  head/sys/modules/hwpmc/Makefile
>>>>>  head/sys/powerpc/include/pmc_mdep.h
>>>>>  head/sys/sys/pmc.h
>>>>>  head/sys/sys/pmckern.h
>>>>>  head/sys/sys/pmclog.h
>>>>>  head/usr.sbin/pmcstat/pmcstat_log.c
>>>>>
>>>>> Modified: head/lib/libpmc/Makefile
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/Makefile    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/Makefile    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -20,6 +20,7 @@ MAN+= pmc_read.3
>>>>>  MAN+=  pmc_set.3
>>>>>  MAN+=  pmc_start.3
>>>>>  MAN+=  pmclog.3
>>>>> +MAN+=  pmc.soft.3
>>>>>
>>>>>  # PMC-dependent manual pages
>>>>>  .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
>>>>>
>>>>> Modified: head/lib/libpmc/libpmc.c
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/libpmc.c    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/libpmc.c    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -77,11 +77,12 @@ static int tsc_allocate_pmc(enum pmc_eve
>>>>>  static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>>>>>     struct pmc_op_pmcallocate *_pmc_config);
>>>>>  #endif
>>>>> -
>>>>>  #if defined(__mips__)
>>>>>  static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>>>>>                             struct pmc_op_pmcallocate *_pmc_config);
>>>>>  #endif /* __mips__ */
>>>>> +static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
>>>>> +    struct pmc_op_pmcallocate *_pmc_config);
>>>>>
>>>>>  #if defined(__powerpc__)
>>>>>  static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec,
>>>>> @@ -156,6 +157,8 @@ PMC_CLASSDEP_TABLE(octeon, OCTEON);
>>>>>  PMC_CLASSDEP_TABLE(ucf, UCF);
>>>>>  PMC_CLASSDEP_TABLE(ppc7450, PPC7450);
>>>>>
>>>>> +static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT];
>>>>> +
>>>>>  #undef __PMC_EV_ALIAS
>>>>>  #define        __PMC_EV_ALIAS(N,CODE)  { N, PMC_EV_##CODE },
>>>>>
>>>>> @@ -215,21 +218,22 @@ static const struct pmc_event_descr west
>>>>>                PMC_CLASS_##C, __VA_ARGS__                      \
>>>>>        }
>>>>>
>>>>> -PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>>>> -PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
>>>>> -PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>>>> -PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>>> -PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>>> -PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>>> -PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
>>>>> -PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
>>>>> -PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
>>>>> -PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC);
>>>>> -PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC);
>>>>> -PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE);
>>>>> -PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K);
>>>>> -PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_OCTEON);
>>>>> -PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_PPC7450);
>>>>> +PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>>>> +PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>>> +PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
>>>>> +PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>>> +PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>>> +PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
>>>>> +PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>>> +PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>>> +PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>>> +PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>>> +PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC);
>>>>> +PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE);
>>>>> +PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K);
>>>>> +PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON);
>>>>> +PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450);
>>>>> +PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT);
>>>>>
>>>>>  static const struct pmc_event_descr tsc_event_table[] =
>>>>>  {
>>>>> @@ -279,16 +283,24 @@ PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc)
>>>>>  #if    defined(__XSCALE__)
>>>>>  PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale);
>>>>>  #endif
>>>>> -
>>>>>  #if defined(__mips__)
>>>>>  PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips);
>>>>>  PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips);
>>>>>  #endif /* __mips__ */
>>>>> -
>>>>>  #if defined(__powerpc__)
>>>>>  PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450);
>>>>>  #endif
>>>>>
>>>>> +static struct pmc_class_descr soft_class_table_descr =
>>>>> +{
>>>>> +       .pm_evc_name  = "SOFT-",
>>>>> +       .pm_evc_name_size = sizeof("SOFT-") - 1,
>>>>> +       .pm_evc_class = PMC_CLASS_SOFT,
>>>>> +       .pm_evc_event_table = NULL,
>>>>> +       .pm_evc_event_table_size = 0,
>>>>> +       .pm_evc_allocate_pmc = soft_allocate_pmc
>>>>> +};
>>>>> +
>>>>>  #undef PMC_CLASS_TABLE_DESC
>>>>>
>>>>>  static const struct pmc_class_descr **pmc_class_table;
>>>>> @@ -343,9 +355,12 @@ static const char * pmc_state_names[] =
>>>>>        __PMC_STATES()
>>>>>  };
>>>>>
>>>>> -static int pmc_syscall = -1;           /* filled in by pmc_init() */
>>>>> -
>>>>> -static struct pmc_cpuinfo cpu_info;    /* filled in by pmc_init() */
>>>>> +/*
>>>>> + * Filled in by pmc_init().
>>>>> + */
>>>>> +static int pmc_syscall = -1;
>>>>> +static struct pmc_cpuinfo cpu_info;
>>>>> +static struct pmc_op_getdyneventinfo soft_event_info;
>>>>>
>>>>>  /* Event masks for events */
>>>>>  struct pmc_masks {
>>>>> @@ -2179,6 +2194,25 @@ tsc_allocate_pmc(enum pmc_event pe, char
>>>>>  }
>>>>>  #endif
>>>>>
>>>>> +static struct pmc_event_alias generic_aliases[] = {
>>>>> +       EV_ALIAS("instructions",                "SOFT-CLOCK.HARD"),
>>>>> +       EV_ALIAS(NULL, NULL)
>>>>> +};
>>>>> +
>>>>> +static int
>>>>> +soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
>>>>> +    struct pmc_op_pmcallocate *pmc_config)
>>>>> +{
>>>>> +       (void)ctrspec;
>>>>> +       (void)pmc_config;
>>>>> +
>>>>> +       if (pe < PMC_EV_SOFT_FIRST || pe > PMC_EV_SOFT_LAST)
>>>>> +               return (-1);
>>>>> +
>>>>> +       pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
>>>>> +       return (0);
>>>>> +}
>>>>> +
>>>>>  #if    defined(__XSCALE__)
>>>>>
>>>>>  static struct pmc_event_alias xscale_aliases[] = {
>>>>> @@ -2663,6 +2697,10 @@ pmc_event_names_of_class(enum pmc_class
>>>>>                ev = ppc7450_event_table;
>>>>>                count = PMC_EVENT_TABLE_SIZE(ppc7450);
>>>>>                break;
>>>>> +       case PMC_CLASS_SOFT:
>>>>> +               ev = soft_event_table;
>>>>> +               count = soft_event_info.pm_nevent;
>>>>> +               break;
>>>>>        default:
>>>>>                errno = EINVAL;
>>>>>                return (-1);
>>>>> @@ -2676,6 +2714,7 @@ pmc_event_names_of_class(enum pmc_class
>>>>>
>>>>>        for (;count--; ev++, names++)
>>>>>                *names = ev->pm_ev_name;
>>>>> +
>>>>>        return (0);
>>>>>  }
>>>>>
>>>>> @@ -2780,11 +2819,34 @@ pmc_init(void)
>>>>>                pmc_class_table[n] = NULL;
>>>>>
>>>>>        /*
>>>>> +        * Get soft events list.
>>>>> +        */
>>>>> +       soft_event_info.pm_class = PMC_CLASS_SOFT;
>>>>> +       if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0)
>>>>> +               return (pmc_syscall = -1);
>>>>> +
>>>>> +       /* Map soft events to static list. */
>>>>> +       for (n = 0; n < soft_event_info.pm_nevent; n++) {
>>>>> +               soft_event_table[n].pm_ev_name =
>>>>> +                   soft_event_info.pm_events[n].pm_ev_name;
>>>>> +               soft_event_table[n].pm_ev_code =
>>>>> +                   soft_event_info.pm_events[n].pm_ev_code;
>>>>> +       }
>>>>> +       soft_class_table_descr.pm_evc_event_table_size = \
>>>>> +           soft_event_info.pm_nevent;
>>>>> +       soft_class_table_descr.pm_evc_event_table = \
>>>>> +           soft_event_table;
>>>>> +
>>>>> +       /*
>>>>>         * Fill in the class table.
>>>>>         */
>>>>>        n = 0;
>>>>> +
>>>>> +       /* Fill soft events information. */
>>>>> +       pmc_class_table[n++] = &soft_class_table_descr;
>>>>>  #if defined(__amd64__) || defined(__i386__)
>>>>> -       pmc_class_table[n++] = &tsc_class_table_descr;
>>>>> +       if (cpu_info.pm_cputype != PMC_CPU_GENERIC)
>>>>> +               pmc_class_table[n++] = &tsc_class_table_descr;
>>>>>
>>>>>        /*
>>>>>         * Check if this CPU has fixed function counters.
>>>>> @@ -2867,6 +2929,9 @@ pmc_init(void)
>>>>>                pmc_class_table[n] = &p4_class_table_descr;
>>>>>                break;
>>>>>  #endif
>>>>> +       case PMC_CPU_GENERIC:
>>>>> +               PMC_MDEP_INIT(generic);
>>>>> +               break;
>>>>>  #if defined(__XSCALE__)
>>>>>        case PMC_CPU_INTEL_XSCALE:
>>>>>                PMC_MDEP_INIT(xscale);
>>>>> @@ -3035,18 +3100,19 @@ _pmc_name_of_event(enum pmc_event pe, en
>>>>>                evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale);
>>>>>        } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) {
>>>>>                ev = mips24k_event_table;
>>>>> -               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k
>>>>> -);
>>>>> +               evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k);
>>>>>        } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) {
>>>>>                ev = octeon_event_table;
>>>>>                evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon);
>>>>>        } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) {
>>>>>                ev = ppc7450_event_table;
>>>>> -               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450
>>>>> -);
>>>>> +               evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450);
>>>>>        } else if (pe == PMC_EV_TSC_TSC) {
>>>>>                ev = tsc_event_table;
>>>>>                evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
>>>>> +       } else if (pe >= PMC_EV_SOFT_FIRST && pe <= PMC_EV_SOFT_LAST) {
>>>>> +               ev = soft_event_table;
>>>>> +               evfence = soft_event_table + soft_event_info.pm_nevent;
>>>>>        }
>>>>>
>>>>>        for (; ev != evfence; ev++)
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.3       Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.3       Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -223,6 +223,8 @@ and
>>>>>  CPUs.
>>>>>  .It Li PMC_CLASS_TSC
>>>>>  The timestamp counter on i386 and amd64 architecture CPUs.
>>>>> +.It Li PMC_CLASS_SOFT
>>>>> +Software events.
>>>>>  .El
>>>>>  .Ss PMC Capabilities
>>>>>  Capabilities of performance monitoring hardware are denoted using
>>>>> @@ -525,6 +527,7 @@ API is
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>  .Xr hwpmc 4 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.atom.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.atom.3  Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -1176,6 +1176,7 @@ and the underlying hardware events used
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.core.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.core.3  Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.core.3  Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -792,6 +792,7 @@ may not count some transitions.
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>  .Xr hwpmc 4
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.core2.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.core2.3 Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -1107,6 +1107,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.corei7.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.corei7.3        Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -1559,6 +1559,7 @@ Counts number of segment register loads.
>>>>>  .Xr pmc.corei7uc 3 ,
>>>>>  .Xr pmc.westmere 3 ,
>>>>>  .Xr pmc.westmereuc 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.corei7uc.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.corei7uc.3      Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -863,6 +863,7 @@ refreshed or needs to go into a power do
>>>>>  .Xr pmc.corei7 3 ,
>>>>>  .Xr pmc.westmere 3 ,
>>>>>  .Xr pmc.westmereuc 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.iaf.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.iaf.3   Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -132,6 +132,7 @@ CPU, use the event specifier
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.k7.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.k7.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -249,6 +249,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>  .Xr hwpmc 4
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.k8.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.k8.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -783,6 +783,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>  .Xr hwpmc 4
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.mips24k.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.mips24k.3       Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -392,6 +392,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.octeon.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.octeon.3        Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -232,6 +232,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.p4.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.p4.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -1208,6 +1208,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc.k8 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>  .Xr hwpmc 4
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.p5.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.p5.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -444,6 +444,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc.k8 3 ,
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>  .Xr hwpmc 4
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.p6.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.p6.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -1010,6 +1010,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc.k8 3 ,
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>  .Xr hwpmc 4
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.sandybridge.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.sandybridge.3   Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -907,6 +907,7 @@ Split locks in SQ.
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>>  .Xr pmc.sandybridgeuc 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc.ucf 3 ,
>>>>>  .Xr pmc.westmere 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.sandybridgeuc.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.sandybridgeuc.3 Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -208,6 +208,7 @@ Counts the number of core-outgoing entri
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>>  .Xr pmc.sandybridge 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc.ucf 3 ,
>>>>>  .Xr pmc.westmere 3 ,
>>>>>
>>>>> Added: head/lib/libpmc/pmc.soft.3
>>>>> ==============================================================================
>>>>> --- /dev/null   00:00:00 1970   (empty, because file is newly added)
>>>>> +++ head/lib/libpmc/pmc.soft.3  Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -0,0 +1,104 @@
>>>>> +.\" Copyright (c) 2012 Fabien Thomas.  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$
>>>>> +.\"
>>>>> +.Dd March 28, 2012
>>>>> +.Os
>>>>> +.Dt PMC.SOFT 3
>>>>> +.Sh NAME
>>>>> +.Nm pmc.soft
>>>>> +.Nd measurements using software based events
>>>>> +.Sh LIBRARY
>>>>> +.Lb libpmc
>>>>> +.Sh SYNOPSIS
>>>>> +.In pmc.h
>>>>> +.Sh DESCRIPTION
>>>>> +Software events are used to collect various source of software events.
>>>>> +.Ss PMC Features
>>>>> +16 sampling counters using software events based on various sources.
>>>>> +These PMCs support the following capabilities:
>>>>> +.Bl -column "PMC_CAP_INTERRUPT" "Support"
>>>>> +.It Em Capability Ta Em Support
>>>>> +.It PMC_CAP_CASCADE Ta \&No
>>>>> +.It PMC_CAP_EDGE Ta \&No
>>>>> +.It PMC_CAP_INTERRUPT Ta Yes
>>>>> +.It PMC_CAP_INVERT Ta \&No
>>>>> +.It PMC_CAP_READ Ta Yes
>>>>> +.It PMC_CAP_PRECISE Ta \&No
>>>>> +.It PMC_CAP_SYSTEM Ta Yes
>>>>> +.It PMC_CAP_TAGGING Ta \&No
>>>>> +.It PMC_CAP_THRESHOLD Ta \&No
>>>>> +.It PMC_CAP_USER Ta Yes
>>>>> +.It PMC_CAP_WRITE Ta Yes
>>>>> +.El
>>>>> +.Ss Event Qualifiers
>>>>> +There is no supported event qualifier.
>>>>> +.Pp
>>>>> +The event specifiers supported by software are:
>>>>> +.Bl -tag -width indent
>>>>> +.It Li CLOCK.HARD
>>>>> +Hard clock ticks.
>>>>> +.It Li CLOCK.STAT
>>>>> +Stat clock ticks.
>>>>> +.It Li LOCK.FAILED
>>>>> +Lock acquisition failed.
>>>>> +.It Li PAGE_FAULT.ALL
>>>>> +All page fault type.
>>>>> +.It Li PAGE_FAULT.READ
>>>>> +Read page fault.
>>>>> +.It Li PAGE_FAULT.WRITE
>>>>> +Write page fault.
>>>>> +.El
>>>>> +.Sh SEE ALSO
>>>>> +.Xr pmc 3 ,
>>>>> +.Xr pmc.atom 3 ,
>>>>> +.Xr pmc.core 3 ,
>>>>> +.Xr pmc.iaf 3 ,
>>>>> +.Xr pmc.ucf 3 ,
>>>>> +.Xr pmc.k7 3 ,
>>>>> +.Xr pmc.k8 3 ,
>>>>> +.Xr pmc.p4 3 ,
>>>>> +.Xr pmc.p5 3 ,
>>>>> +.Xr pmc.p6 3 ,
>>>>> +.Xr pmc.corei7 3 ,
>>>>> +.Xr pmc.corei7uc 3 ,
>>>>> +.Xr pmc.westmereuc 3 ,
>>>>> +.Xr pmc.tsc 3 ,
>>>>> +.Xr pmc_cpuinfo 3 ,
>>>>> +.Xr pmclog 3 ,
>>>>> +.Xr hwpmc 4
>>>>> +.Sh HISTORY
>>>>> +The
>>>>> +.Nm pmc
>>>>> +library first appeared in
>>>>> +.Fx 6.0 .
>>>>> +.Sh AUTHORS
>>>>> +The
>>>>> +.Lb libpmc
>>>>> +library was written by
>>>>> +.An "Joseph Koshy"
>>>>> +.Aq [hidden email] .
>>>>> +Software PMC was written by
>>>>> +.An "Fabien Thomas"
>>>>> +.Aq [hidden email] .
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.tsc.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.tsc.3   Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -68,6 +68,7 @@ maps to the TSC.
>>>>>  .Xr pmc.p4 3 ,
>>>>>  .Xr pmc.p5 3 ,
>>>>>  .Xr pmc.p6 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>  .Xr hwpmc 4
>>>>>  .Sh HISTORY
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.ucf.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.ucf.3   Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -96,6 +96,7 @@ offset C0H under device number 0 and Fun
>>>>>  .Xr pmc.corei7uc 3 ,
>>>>>  .Xr pmc.westmere 3 ,
>>>>>  .Xr pmc.westmereuc 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.westmere.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.westmere.3      Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -1381,6 +1381,7 @@ Counts number of SID integer 64 bit shif
>>>>>  .Xr pmc.corei7 3 ,
>>>>>  .Xr pmc.corei7uc 3 ,
>>>>>  .Xr pmc.westmereuc 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.westmereuc.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.westmereuc.3    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -1066,6 +1066,7 @@ disabled.
>>>>>  .Xr pmc.corei7 3 ,
>>>>>  .Xr pmc.corei7uc 3 ,
>>>>>  .Xr pmc.westmere 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr pmc.tsc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>>
>>>>> Modified: head/lib/libpmc/pmc.xscale.3
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmc.xscale.3        Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -134,6 +134,7 @@ and the underlying hardware events used.
>>>>>  .Xr pmc 3 ,
>>>>>  .Xr pmc_cpuinfo 3 ,
>>>>>  .Xr pmclog 3 ,
>>>>> +.Xr pmc.soft 3 ,
>>>>>  .Xr hwpmc 4
>>>>>  .Sh HISTORY
>>>>>  The
>>>>>
>>>>> Modified: head/lib/libpmc/pmclog.c
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmclog.c    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmclog.c    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -369,6 +369,12 @@ pmclog_get_event(void *cookie, char **da
>>>>>                    == NULL)
>>>>>                        goto error;
>>>>>                break;
>>>>> +       case PMCLOG_TYPE_PMCALLOCATEDYN:
>>>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_pmcid);
>>>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_event);
>>>>> +               PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_flags);
>>>>> +               PMCLOG_READSTRING(le,ev->pl_u.pl_ad.pl_evname,PMC_NAME_MAX);
>>>>> +               break;
>>>>>        case PMCLOG_TYPE_PMCATTACH:
>>>>>                PMCLOG_GET_PATHLEN(pathlen,evlen,pmclog_pmcattach);
>>>>>                PMCLOG_READ32(le,ev->pl_u.pl_t.pl_pmcid);
>>>>>
>>>>> Modified: head/lib/libpmc/pmclog.h
>>>>> ==============================================================================
>>>>> --- head/lib/libpmc/pmclog.h    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/lib/libpmc/pmclog.h    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -88,6 +88,13 @@ struct pmclog_ev_pmcallocate {
>>>>>        pmc_id_t        pl_pmcid;
>>>>>  };
>>>>>
>>>>> +struct pmclog_ev_pmcallocatedyn {
>>>>> +       uint32_t        pl_event;
>>>>> +       char            pl_evname[PMC_NAME_MAX];
>>>>> +       uint32_t        pl_flags;
>>>>> +       pmc_id_t        pl_pmcid;
>>>>> +};
>>>>> +
>>>>>  struct pmclog_ev_pmcattach {
>>>>>        pmc_id_t        pl_pmcid;
>>>>>        pid_t           pl_pid;
>>>>> @@ -146,6 +153,7 @@ struct pmclog_ev {
>>>>>                struct pmclog_ev_map_out        pl_mo;
>>>>>                struct pmclog_ev_pcsample       pl_s;
>>>>>                struct pmclog_ev_pmcallocate    pl_a;
>>>>> +               struct pmclog_ev_pmcallocatedyn pl_ad;
>>>>>                struct pmclog_ev_pmcattach      pl_t;
>>>>>                struct pmclog_ev_pmcdetach      pl_d;
>>>>>                struct pmclog_ev_proccsw        pl_c;
>>>>>
>>>>> Modified: head/sys/amd64/amd64/trap.c
>>>>> ==============================================================================
>>>>> --- head/sys/amd64/amd64/trap.c Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/amd64/amd64/trap.c Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
>>>>>  #include <sys/vmmeter.h>
>>>>>  #ifdef HWPMC_HOOKS
>>>>>  #include <sys/pmckern.h>
>>>>> +PMC_SOFT_DEFINE( , , page_fault, all);
>>>>> +PMC_SOFT_DEFINE( , , page_fault, read);
>>>>> +PMC_SOFT_DEFINE( , , page_fault, write);
>>>>>  #endif
>>>>>
>>>>>  #include <vm/vm.h>
>>>>> @@ -743,8 +746,20 @@ trap_pfault(frame, usermode)
>>>>>                 */
>>>>>                rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
>>>>>        }
>>>>> -       if (rv == KERN_SUCCESS)
>>>>> +       if (rv == KERN_SUCCESS) {
>>>>> +#ifdef HWPMC_HOOKS
>>>>> +               if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
>>>>> +                       PMC_SOFT_CALL_TF( , , page_fault, all, frame);
>>>>> +                       if (ftype == VM_PROT_READ)
>>>>> +                               PMC_SOFT_CALL_TF( , , page_fault, read,
>>>>> +                                   frame);
>>>>> +                       else
>>>>> +                               PMC_SOFT_CALL_TF( , , page_fault, write,
>>>>> +                                   frame);
>>>>> +               }
>>>>> +#endif
>>>>>                return (0);
>>>>> +       }
>>>>>  nogo:
>>>>>        if (!usermode) {
>>>>>                if (td->td_intr_nesting_level == 0 &&
>>>>>
>>>>> Modified: head/sys/amd64/include/pmc_mdep.h
>>>>> ==============================================================================
>>>>> --- head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/amd64/include/pmc_mdep.h   Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -50,13 +50,13 @@ struct pmc_mdep;
>>>>>  * measurement architecture have PMCs of the following classes: TSC,
>>>>>  * IAF, IAP, UCF and UCP.
>>>>>  */
>>>>> -#define        PMC_MDEP_CLASS_INDEX_TSC        0
>>>>> -#define        PMC_MDEP_CLASS_INDEX_K8         1
>>>>> -#define        PMC_MDEP_CLASS_INDEX_P4         1
>>>>> -#define        PMC_MDEP_CLASS_INDEX_IAP        1
>>>>> -#define        PMC_MDEP_CLASS_INDEX_IAF        2
>>>>> -#define        PMC_MDEP_CLASS_INDEX_UCP        3
>>>>> -#define        PMC_MDEP_CLASS_INDEX_UCF        4
>>>>> +#define        PMC_MDEP_CLASS_INDEX_TSC        1
>>>>> +#define        PMC_MDEP_CLASS_INDEX_K8         2
>>>>> +#define        PMC_MDEP_CLASS_INDEX_P4         2
>>>>> +#define        PMC_MDEP_CLASS_INDEX_IAP        2
>>>>> +#define        PMC_MDEP_CLASS_INDEX_IAF        3
>>>>> +#define        PMC_MDEP_CLASS_INDEX_UCP        4
>>>>> +#define        PMC_MDEP_CLASS_INDEX_UCF        5
>>>>>
>>>>>  /*
>>>>>  * On the amd64 platform we support the following PMCs.
>>>>> @@ -119,6 +119,15 @@ union pmc_md_pmc {
>>>>>
>>>>>  #define        PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
>>>>>
>>>>> +/* Build a fake kernel trapframe from current instruction pointer. */
>>>>> +#define PMC_FAKE_TRAPFRAME(TF)                                         \
>>>>> +       do {                                                            \
>>>>> +       (TF)->tf_cs = 0; (TF)->tf_rflags = 0;                           \
>>>>> +       __asm __volatile("movq %%rbp,%0" : "=r" ((TF)->tf_rbp));        \
>>>>> +       __asm __volatile("movq %%rsp,%0" : "=r" ((TF)->tf_rsp));        \
>>>>> +       __asm __volatile("call 1f \n\t1: pop %0" : "=r"((TF)->tf_rip)); \
>>>>> +       } while (0)
>>>>> +
>>>>>  /*
>>>>>  * Prototypes
>>>>>  */
>>>>>
>>>>> Modified: head/sys/arm/include/pmc_mdep.h
>>>>> ==============================================================================
>>>>> --- head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/arm/include/pmc_mdep.h     Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -29,7 +29,7 @@
>>>>>  #ifndef _MACHINE_PMC_MDEP_H_
>>>>>  #define        _MACHINE_PMC_MDEP_H_
>>>>>
>>>>> -#define        PMC_MDEP_CLASS_INDEX_XSCALE     0
>>>>> +#define        PMC_MDEP_CLASS_INDEX_XSCALE     1
>>>>>  /*
>>>>>  * On the ARM platform we support the following PMCs.
>>>>>  *
>>>>>
>>>>> Modified: head/sys/conf/files
>>>>> ==============================================================================
>>>>> --- head/sys/conf/files Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/conf/files Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -1260,6 +1260,7 @@ dev/hme/if_hme_sbus.c             optional hme sbus
>>>>>  dev/hptiop/hptiop.c            optional hptiop scbus
>>>>>  dev/hwpmc/hwpmc_logging.c      optional hwpmc
>>>>>  dev/hwpmc/hwpmc_mod.c          optional hwpmc
>>>>> +dev/hwpmc/hwpmc_soft.c         optional hwpmc
>>>>>  dev/ichsmb/ichsmb.c            optional ichsmb
>>>>>  dev/ichsmb/ichsmb_pci.c                optional ichsmb pci
>>>>>  dev/ida/ida.c                  optional ida
>>>>>
>>>>> Modified: head/sys/dev/hwpmc/hwpmc_amd.c
>>>>> ==============================================================================
>>>>> --- head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/dev/hwpmc/hwpmc_amd.c      Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -687,7 +687,8 @@ amd_intr(int cpu, struct trapframe *tf)
>>>>>                wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
>>>>>
>>>>>                /* Restart the counter if logging succeeded. */
>>>>> -               error = pmc_process_interrupt(cpu, pm, tf, TRAPF_USERMODE(tf));
>>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>> +                   TRAPF_USERMODE(tf));
>>>>>                if (error == 0)
>>>>>                        wrmsr(evsel, config | AMD_PMC_ENABLE);
>>>>>        }
>>>>> @@ -874,7 +875,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int c
>>>>>  struct pmc_mdep *
>>>>>  pmc_amd_initialize(void)
>>>>>  {
>>>>> -       int classindex, error, i, nclasses, ncpus;
>>>>> +       int classindex, error, i, ncpus;
>>>>>        struct pmc_classdep *pcd;
>>>>>        enum pmc_cputype cputype;
>>>>>        struct pmc_mdep *pmc_mdep;
>>>>> @@ -926,12 +927,9 @@ pmc_amd_initialize(void)
>>>>>         * These processors have two classes of PMCs: the TSC and
>>>>>         * programmable PMCs.
>>>>>         */
>>>>> -       nclasses = 2;
>>>>> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses * sizeof (struct pmc_classdep),
>>>>> -           M_PMC, M_WAITOK|M_ZERO);
>>>>> +       pmc_mdep = pmc_mdep_alloc(2);
>>>>>
>>>>>        pmc_mdep->pmd_cputype = cputype;
>>>>> -       pmc_mdep->pmd_nclass  = nclasses;
>>>>>
>>>>>        ncpus = pmc_cpu_max();
>>>>>
>>>>>
>>>>> Modified: head/sys/dev/hwpmc/hwpmc_core.c
>>>>> ==============================================================================
>>>>> --- head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/dev/hwpmc/hwpmc_core.c     Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -2239,7 +2239,7 @@ core_intr(int cpu, struct trapframe *tf)
>>>>>                if (pm->pm_state != PMC_STATE_RUNNING)
>>>>>                        continue;
>>>>>
>>>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>>                    TRAPF_USERMODE(tf));
>>>>>
>>>>>                v = pm->pm_sc.pm_reloadcount;
>>>>> @@ -2326,7 +2326,7 @@ core2_intr(int cpu, struct trapframe *tf
>>>>>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>>>>>                        continue;
>>>>>
>>>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>>                    TRAPF_USERMODE(tf));
>>>>>                if (error)
>>>>>                        intrenable &= ~flag;
>>>>> @@ -2354,7 +2354,7 @@ core2_intr(int cpu, struct trapframe *tf
>>>>>                    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
>>>>>                        continue;
>>>>>
>>>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>>                    TRAPF_USERMODE(tf));
>>>>>                if (error)
>>>>>                        intrenable &= ~flag;
>>>>>
>>>>> Modified: head/sys/dev/hwpmc/hwpmc_intel.c
>>>>> ==============================================================================
>>>>> --- head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/dev/hwpmc/hwpmc_intel.c    Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -162,12 +162,10 @@ pmc_intel_initialize(void)
>>>>>                return (NULL);
>>>>>        }
>>>>>
>>>>> -       pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses *
>>>>> -           sizeof(struct pmc_classdep), M_PMC, M_WAITOK|M_ZERO);
>>>>> +       /* Allocate base class and initialize machine dependent struct */
>>>>> +       pmc_mdep = pmc_mdep_alloc(nclasses);
>>>>>
>>>>>        pmc_mdep->pmd_cputype    = cputype;
>>>>> -       pmc_mdep->pmd_nclass     = nclasses;
>>>>> -
>>>>>        pmc_mdep->pmd_switch_in  = intel_switch_in;
>>>>>        pmc_mdep->pmd_switch_out = intel_switch_out;
>>>>>
>>>>>
>>>>> Modified: head/sys/dev/hwpmc/hwpmc_logging.c
>>>>> ==============================================================================
>>>>> --- head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/dev/hwpmc/hwpmc_logging.c  Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -129,6 +129,7 @@ static struct mtx pmc_kthread_mtx;  /* sl
>>>>>
>>>>>  /* Emit a string.  Caution: does NOT update _le, so needs to be last */
>>>>>  #define        PMCLOG_EMITSTRING(S,L)  do { bcopy((S), _le, (L)); } while (0)
>>>>> +#define        PMCLOG_EMITNULLSTRING(L) do { bzero(_le, (L)); } while (0)
>>>>>
>>>>>  #define        PMCLOG_DESPATCH(PO)                                             \
>>>>>                pmclog_release((PO));                                   \
>>>>> @@ -835,16 +836,33 @@ void
>>>>>  pmclog_process_pmcallocate(struct pmc *pm)
>>>>>  {
>>>>>        struct pmc_owner *po;
>>>>> +       struct pmc_soft *ps;
>>>>>
>>>>>        po = pm->pm_owner;
>>>>>
>>>>>        PMCDBG(LOG,ALL,1, "pm=%p", pm);
>>>>>
>>>>> -       PMCLOG_RESERVE(po, PMCALLOCATE, sizeof(struct pmclog_pmcallocate));
>>>>> -       PMCLOG_EMIT32(pm->pm_id);
>>>>> -       PMCLOG_EMIT32(pm->pm_event);
>>>>> -       PMCLOG_EMIT32(pm->pm_flags);
>>>>> -       PMCLOG_DESPATCH(po);
>>>>> +       if (PMC_TO_CLASS(pm) == PMC_CLASS_SOFT) {
>>>>> +               PMCLOG_RESERVE(po, PMCALLOCATEDYN,
>>>>> +                   sizeof(struct pmclog_pmcallocatedyn));
>>>>> +               PMCLOG_EMIT32(pm->pm_id);
>>>>> +               PMCLOG_EMIT32(pm->pm_event);
>>>>> +               PMCLOG_EMIT32(pm->pm_flags);
>>>>> +               ps = pmc_soft_ev_acquire(pm->pm_event);
>>>>> +               if (ps != NULL)
>>>>> +                       PMCLOG_EMITSTRING(ps->ps_ev.pm_ev_name,PMC_NAME_MAX);
>>>>> +               else
>>>>> +                       PMCLOG_EMITNULLSTRING(PMC_NAME_MAX);
>>>>> +               pmc_soft_ev_release(ps);
>>>>> +               PMCLOG_DESPATCH(po);
>>>>> +       } else {
>>>>> +               PMCLOG_RESERVE(po, PMCALLOCATE,
>>>>> +                   sizeof(struct pmclog_pmcallocate));
>>>>> +               PMCLOG_EMIT32(pm->pm_id);
>>>>> +               PMCLOG_EMIT32(pm->pm_event);
>>>>> +               PMCLOG_EMIT32(pm->pm_flags);
>>>>> +               PMCLOG_DESPATCH(po);
>>>>> +       }
>>>>>  }
>>>>>
>>>>>  void
>>>>>
>>>>> Modified: head/sys/dev/hwpmc/hwpmc_mips.c
>>>>> ==============================================================================
>>>>> --- head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/dev/hwpmc/hwpmc_mips.c     Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -287,7 +287,7 @@ mips_pmc_intr(int cpu, struct trapframe
>>>>>                retval = 1;
>>>>>                if (pm->pm_state != PMC_STATE_RUNNING)
>>>>>                        continue;
>>>>> -               error = pmc_process_interrupt(cpu, pm, tf,
>>>>> +               error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
>>>>>                    TRAPF_USERMODE(tf));
>>>>>                if (error) {
>>>>>                        /* Clear/disable the relevant counter */
>>>>>
>>>>> Modified: head/sys/dev/hwpmc/hwpmc_mod.c
>>>>> ==============================================================================
>>>>> --- head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:49:11 2012        (r233627)
>>>>> +++ head/sys/dev/hwpmc/hwpmc_mod.c      Wed Mar 28 20:58:30 2012        (r233628)
>>>>> @@ -70,6 +70,8 @@ __FBSDID("$FreeBSD$");
>>>>>  #include <vm/vm_map.h>
>>>>>  #include <vm/vm_object.h>
>>>>>
>>>>> +#include "hwpmc_soft.h"
>>>>> +
>>>>>  /*
>>>>>  * Types
>>>>>  */
>>>>> @@ -182,7 +184,7 @@ static int  pmc_attach_one_process(struct
>>>>>  static int     pmc_can_allocate_rowindex(struct proc *p, unsigned int ri,
>>>>>     int cpu);
>>>>>  static int     pmc_can_attach(struct pmc *pm, struct proc *p);
>>>>> -static void    pmc_capture_user_callchain(int cpu, struct trapframe *tf);
>>>>> +static void    pmc_capture_user_callchain(int cpu, int soft, struct trapframe *tf);
>>>>>  static void    pmc_cleanup(void);
>>>>>  static int     pmc_detach_process(struct proc *p, struct pmc *pm);
>>>>>  static int     pmc_detach_one_process(struct proc *p, struct pmc *pm,
>>>>> @@ -206,7 +208,7 @@ static void pmc_process_csw_out(struct t
>>>>>  static void    pmc_process_exit(void *arg, struct proc *p);
>>>>>  static void    pmc_process_fork(void *arg, struct proc *p1,
>>>>>     struct proc *p2, int n);
>>>>> -static void    pmc_process_samples(int cpu);
>>>>> +static void    pmc_process_samples(int cpu, int soft);
>>>>>  static void    pmc_release_pmc_descriptor(struct pmc *pmc);
>>>>>  static void    pmc_remove_owner(struct pmc_owner *po);
>>>>>  static void    pmc_remove_process_descriptor(struct pmc_process *pp);
>>>>> @@ -218,12 +220,16 @@ static int        pmc_stop(struct pmc *pm);
>>>>>  static int     pmc_syscall_handler(struct thread *td, void *syscall_args);
>>>>>  static void    pmc_unlink_target_process(struct pmc *pmc,
>>>>>     struct pmc_process *pp);
>>>>> +static int generic_switch_in(struct pmc_cpu *pc, struct pmc_process *pp);
>>>>> +static int generic_switch_out(struct pmc_cpu *pc, struct pmc_process *pp);
>>>>> +static struct pmc_mdep *pmc_generic_cpu_initialize(void);
>>>>> +static void pmc_generic_cpu_finalize(struct pmc_mdep *md);
>>>>>
>>>>>  /*
>>>>>  * Kernel tunables and sysctl(8) interface.
>>>>>  */
>>>>>
>>>>> -SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0, "HWPMC parameters");
>>>>> +SYSCTL_DECL(_kern_hwpmc);
>>>>>
>>>>>  static int pmc_callchaindepth = PMC_CALLCHAIN_DEPTH;
>>>>>  TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "callchaindepth", &pmc_callchaindepth);
>>>>> @@ -1833,7 +1839,9 @@ const char *pmc_hooknames[] = {
>>>>>        "KLDUNLOAD",
>>>>>        "MMAP",
>>>>>        "MUNMAP",
>>>>> -       "CALLCHAIN"
>>>>> +       "CALLCHAIN-NMI",
>>>>> +       "CALLCHAIN-SOFT",
>>>>> +       "SOFTSAMPLING"
>>>>>  };
>>>>>  #endif
>>>>>
>>>>> @@ -1992,7 +2000,8 @@ pmc_hook_handler(struct thread *td, int
>>>>>                 * lose the interrupt sample.
>>>>>                 */
>>>>>                CPU_CLR_ATOMIC(PCPU_GET(cpuid), &pmc_cpumask);
>>>>> -               pmc_process_samples(PCPU_GET(cpuid));
>>>>> +               pmc_process_samples(PCPU_GET(cpuid), PMC_HR);
>>>>> +               pmc_process_samples(PCPU_GET(cpuid), PMC_SR);
>>>>>                break;
>>>>>
>>>>>
>>>>> @@ -2022,11 +2031,30 @@ pmc_hook_handler(struct thread *td, int
>>>>>                 */
>>>>>                KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>>>>>                    __LINE__));
>>>>> -               pmc_capture_user_callchain(PCPU_GET(cpuid),
>>>>> +
>>>>> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_HR,
>>>>>                    (struct trapframe *) arg);
>>>>>                td->td_pflags &= ~TDP_CALLCHAIN;
>>>>>                break;
>>>>>
>>>>> +       case PMC_FN_USER_CALLCHAIN_SOFT:
>>>>> +               /*
>>>>> +                * Record a call chain.
>>>>> +                */
>>>>> +               KASSERT(td == curthread, ("[pmc,%d] td != curthread",
>>>>> +                   __LINE__));
>>>>> +               pmc_capture_user_callchain(PCPU_GET(cpuid), PMC_SR,
>>>>> +                   (struct trapframe *) arg);
>>>>> +               td->td_pflags &= ~TDP_CALLCHAIN;
>>>>> +               break;
>>>>> +
>>>>> +       case PMC_FN_SOFT_SAMPLING:
>>>>> +               /*
>>>>> +                * Call soft PMC sampling intr.
>>>>> +                */
>>>>> +               pmc_soft_intr((struct pmckern_soft *) arg);
>>>>> +               break;
>>>>> +
>>>>>        default:
>>>>>  #ifdef DEBUG
>>>>>                KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
>>>>> @@ -2221,18 +2249,17 @@ pmc_destroy_pmc_descriptor(struct pmc *p
>>>>>  static void
>>>>>  pmc_wait_for_pmc_idle(struct pmc *pm)
>>>>>  {
>>>>> -#ifdef DEBUG
>>>>> +#ifdef DEBUG
>>>>>        volatile int maxloop;
>>>>>
>>>>>        maxloop = 100 * pmc_cpu_max();
>>>>>  #endif
>>>>> -
>>>>>        /*
>>>>>         * Loop (with a forced context switch) till the PMC's runcount
>>>>>         * comes down to zero.
>>>>>         */
>>>>>        while (atomic_load_acq_32(&pm->pm_runcount) > 0) {
>>>>> -#ifdef DEBUG
>>>>> +#ifdef DEBUG
>>>>>                maxloop--;
>>>>>                KASSERT(maxloop > 0,
>>>>>                    ("[pmc,%d] (ri%d, rc%d) waiting too long for "
>>>>> @@ -2972,6 +2999,53 @@ pmc_syscall_handler(struct thread *td, v
>>>>>        }
>>>>>        break;
>>>>>
>>>>> +       /*
>>>>> +        * Retrieve soft events list.
>>>>> +        */
>>>>> +       case PMC_OP_GETDYNEVENTINFO:
>>>>> +       {
>>>>> +               enum pmc_class                  cl;
>>>>> +               enum pmc_event                  ev;
>>>>> +               struct pmc_op_getdyneventinfo   *gei;
>>>>> +               struct pmc_dyn_event_descr      dev;
>>>>> +               struct pmc_soft                 *ps;
>>>>> +               uint32_t                        nevent;
>>>>> +
>>>>> +               sx_assert(&pmc_sx, SX_LOCKED);
>>>>> +
>>>>> +               gei = (struct pmc_op_getdyneventinfo *) arg;
>>>>> +
>>>>> +               if ((error = copyin(&gei->pm_class, &cl, sizeof(cl))) != 0)
>>>>> +                       break;
>>>>> +
>>>>> +               /* Only SOFT class is dynamic. */
>>>>> +               if (cl != PMC_CLASS_SOFT) {
>>>>> +                       error = EINVAL;
>>>>> +                       break;
>>>>> +               }
>>>>> +
>>>>> +               nevent = 0;
>>>>> +               for (ev = PMC_EV_SOFT_FIRST; ev <= PMC_EV_SOFT_LAST; ev++) {
>>>>> +                       ps = pmc_soft_ev_acquire(ev);
>>>>> +                       if (ps == NULL)
>>>>> +                               continue;
>>>>> +                       bcopy(&ps->ps_ev, &dev, sizeof(dev));
>>>>> +                       pmc_soft_ev_release(ps);
>>>>> +
>>>>> +                       error = copyout(&dev,
>>>>> +                           &gei->pm_events[nevent],
>>>>> +                           sizeof(struct pmc_dyn_event_descr));
>>>>> +                       if (error != 0)
>>>>> +                               break;
>>>>> +                       nevent++;
>>>>> +               }
>>>>> +               if (error != 0)
>>>>> +                       break;
>>>>> +
>>>>> +               error = copyout(&nevent, &gei->pm_nevent,
>>>>>
>>>>> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
>>>
>>>
>>>
>>> --
>>> Monthadar Al Jaberi
>>> <RSPRO_USB_PROD>
>>
>>
>
>
>
> --
> Monthadar Al Jaberi

Loading...