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...

From: Adrian Chadd <adrian_at_freebsd.org>
Date: Sun, 22 Apr 2012 23:44:12 -0700
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 <fabient_at_freebsd.org> 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)
> _at__at_ -20,6 +20,7 _at__at_ 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)
> _at__at_ -77,11 +77,12 _at__at_ 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,
> _at__at_ -156,6 +157,8 _at__at_ 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 },
>
> _at__at_ -215,21 +218,22 _at__at_ 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[] =
>  {
> _at__at_ -279,16 +283,24 _at__at_ 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;
> _at__at_ -343,9 +355,12 _at__at_ 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 {
> _at__at_ -2179,6 +2194,25 _at__at_ 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[] = {
> _at__at_ -2663,6 +2697,10 _at__at_ 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);
> _at__at_ -2676,6 +2714,7 _at__at_ pmc_event_names_of_class(enum pmc_class
>
>        for (;count--; ev++, names++)
>                *names = ev->pm_ev_name;
> +
>        return (0);
>  }
>
> _at__at_ -2780,11 +2819,34 _at__at_ 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.
> _at__at_ -2867,6 +2929,9 _at__at_ 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);
> _at__at_ -3035,18 +3100,19 _at__at_ _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)
> _at__at_ -223,6 +223,8 _at__at_ 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
> _at__at_ -525,6 +527,7 _at__at_ 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)
> _at__at_ -1176,6 +1176,7 _at__at_ 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)
> _at__at_ -792,6 +792,7 _at__at_ 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)
> _at__at_ -1107,6 +1107,7 _at__at_ 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)
> _at__at_ -1559,6 +1559,7 _at__at_ 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)
> _at__at_ -863,6 +863,7 _at__at_ 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)
> _at__at_ -132,6 +132,7 _at__at_ 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)
> _at__at_ -249,6 +249,7 _at__at_ 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)
> _at__at_ -783,6 +783,7 _at__at_ 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)
> _at__at_ -392,6 +392,7 _at__at_ 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)
> _at__at_ -232,6 +232,7 _at__at_ 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)
> _at__at_ -1208,6 +1208,7 _at__at_ 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)
> _at__at_ -444,6 +444,7 _at__at_ 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)
> _at__at_ -1010,6 +1010,7 _at__at_ 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)
> _at__at_ -907,6 +907,7 _at__at_ 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)
> _at__at_ -208,6 +208,7 _at__at_ 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)
> _at__at_ -0,0 +1,104 _at__at_
> +.\" 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 jkoshy_at_FreeBSD.org .
> +Software PMC was written by
> +.An "Fabien Thomas"
> +.Aq fabient_at_FreeBSD.org .
>
> 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)
> _at__at_ -68,6 +68,7 _at__at_ 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)
> _at__at_ -96,6 +96,7 _at__at_ 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)
> _at__at_ -1381,6 +1381,7 _at__at_ 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)
> _at__at_ -1066,6 +1066,7 _at__at_ 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)
> _at__at_ -134,6 +134,7 _at__at_ 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)
> _at__at_ -369,6 +369,12 _at__at_ 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)
> _at__at_ -88,6 +88,13 _at__at_ 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;
> _at__at_ -146,6 +153,7 _at__at_ 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)
> _at__at_ -71,6 +71,9 _at__at_ __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>
> _at__at_ -743,8 +746,20 _at__at_ 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)
> _at__at_ -50,13 +50,13 _at__at_ 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.
> _at__at_ -119,6 +119,15 _at__at_ 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)
> _at__at_ -29,7 +29,7 _at__at_
>  #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)
> _at__at_ -1260,6 +1260,7 _at__at_ 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)
> _at__at_ -687,7 +687,8 _at__at_ 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);
>        }
> _at__at_ -874,7 +875,7 _at__at_ 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;
> _at__at_ -926,12 +927,9 _at__at_ 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)
> _at__at_ -2239,7 +2239,7 _at__at_ 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;
> _at__at_ -2326,7 +2326,7 _at__at_ 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;
> _at__at_ -2354,7 +2354,7 _at__at_ 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)
> _at__at_ -162,12 +162,10 _at__at_ 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)
> _at__at_ -129,6 +129,7 _at__at_ 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));                                   \
> _at__at_ -835,16 +836,33 _at__at_ 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)
> _at__at_ -287,7 +287,7 _at__at_ 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)
> _at__at_ -70,6 +70,8 _at__at_ __FBSDID("$FreeBSD$");
>  #include <vm/vm_map.h>
>  #include <vm/vm_object.h>
>
> +#include "hwpmc_soft.h"
> +
>  /*
>  * Types
>  */
> _at__at_ -182,7 +184,7 _at__at_ 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,
> _at__at_ -206,7 +208,7 _at__at_ 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);
> _at__at_ -218,12 +220,16 _at__at_ 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);
> _at__at_ -1833,7 +1839,9 _at__at_ const char *pmc_hooknames[] = {
>        "KLDUNLOAD",
>        "MMAP",
>        "MUNMAP",
> -       "CALLCHAIN"
> +       "CALLCHAIN-NMI",
> +       "CALLCHAIN-SOFT",
> +       "SOFTSAMPLING"
>  };
>  #endif
>
> _at__at_ -1992,7 +2000,8 _at__at_ 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;
>
>
> _at__at_ -2022,11 +2031,30 _at__at_ 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));
> _at__at_ -2221,18 +2249,17 _at__at_ 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 "
> _at__at_ -2972,6 +2999,53 _at__at_ 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 ***
Received on Mon Apr 23 2012 - 04:44:13 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:26 UTC