From owner-p4-projects@FreeBSD.ORG Sun May 1 22:12:58 2005 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id A112B16A4D0; Sun, 1 May 2005 22:12:57 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 648F616A4CE for ; Sun, 1 May 2005 22:12:57 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id D8E1443D2F for ; Sun, 1 May 2005 22:12:56 +0000 (GMT) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j41MCuTw079616 for ; Sun, 1 May 2005 22:12:56 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j41MCutH079613 for perforce@freebsd.org; Sun, 1 May 2005 22:12:56 GMT (envelope-from sam@freebsd.org) Date: Sun, 1 May 2005 22:12:56 GMT Message-Id: <200505012212.j41MCutH079613@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 76346 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 01 May 2005 22:12:58 -0000 http://perforce.freebsd.org/chv.cgi?CH=76346 Change 76346 by sam@sam_ebb on 2005/05/01 22:12:29 IFC @ 76340 Affected files ... .. //depot/projects/wifi/sys/conf/options.pc98#5 integrate .. //depot/projects/wifi/sys/dev/ata/ata-chipset.c#11 integrate .. //depot/projects/wifi/sys/dev/ata/ata-dma.c#6 integrate .. //depot/projects/wifi/sys/dev/ata/ata-lowlevel.c#11 integrate .. //depot/projects/wifi/sys/dev/ata/ata-pci.c#7 integrate .. //depot/projects/wifi/sys/dev/ata/ata-raid.h#6 integrate .. //depot/projects/wifi/sys/dev/hwpmc/hwpmc_amd.c#2 integrate .. //depot/projects/wifi/sys/dev/hwpmc/hwpmc_intel.c#2 integrate .. //depot/projects/wifi/sys/dev/hwpmc/hwpmc_mod.c#2 integrate .. //depot/projects/wifi/sys/dev/hwpmc/hwpmc_piv.c#2 integrate .. //depot/projects/wifi/sys/dev/hwpmc/hwpmc_ppro.c#2 integrate .. //depot/projects/wifi/sys/fs/devfs/devfs_vnops.c#21 integrate .. //depot/projects/wifi/sys/geom/geom_pc98_enc.c#2 integrate .. //depot/projects/wifi/sys/i386/include/pmc_mdep.h#4 integrate .. //depot/projects/wifi/sys/kern/kern_exec.c#12 integrate .. //depot/projects/wifi/sys/kern/subr_taskqueue.c#3 integrate .. //depot/projects/wifi/sys/kern/vfs_cluster.c#10 integrate .. //depot/projects/wifi/sys/kern/vfs_default.c#17 integrate .. //depot/projects/wifi/sys/kern/vfs_mount.c#20 integrate .. //depot/projects/wifi/sys/kern/vfs_subr.c#24 integrate .. //depot/projects/wifi/sys/netinet/tcp_usrreq.c#11 integrate .. //depot/projects/wifi/sys/pc98/conf/NOTES#10 integrate .. //depot/projects/wifi/sys/powerpc/powermac/ata_kauai.c#8 integrate .. //depot/projects/wifi/sys/powerpc/powermac/ata_macio.c#8 integrate .. //depot/projects/wifi/sys/sys/diskpc98.h#3 integrate .. //depot/projects/wifi/sys/sys/pmc.h#4 integrate .. //depot/projects/wifi/sys/sys/taskqueue.h#3 integrate Differences ... ==== //depot/projects/wifi/sys/conf/options.pc98#5 (text+ko) ==== @@ -1,4 +1,4 @@ -# $FreeBSD: src/sys/conf/options.pc98,v 1.183 2005/04/15 14:24:49 nyan Exp $ +# $FreeBSD: src/sys/conf/options.pc98,v 1.184 2005/05/01 03:59:25 nyan Exp $ # Options specific to the pc98 platform kernels AUTO_EOI_1 opt_auto_eoi.h @@ -102,3 +102,6 @@ DEV_APIC opt_apic.h DEV_MECIA opt_mecia.h DEV_NPX opt_npx.h + +# Debugging +KDB_STOP_NMI opt_global.h ==== //depot/projects/wifi/sys/dev/ata/ata-chipset.c#11 (text+ko) ==== @@ -27,7 +27,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/ata/ata-chipset.c,v 1.114 2005/04/30 16:22:06 sos Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/ata/ata-chipset.c,v 1.115 2005/05/01 12:24:45 sos Exp $"); #include "opt_ata.h" #include @@ -2004,7 +2004,7 @@ static int ata_promise_mio_dmastart(device_t dev) { - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); ch->flags |= ATA_DMA_ACTIVE; return 0; @@ -2013,7 +2013,7 @@ static int ata_promise_mio_dmastop(device_t dev) { - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); ch->flags &= ~ATA_DMA_ACTIVE; /* get status XXX SOS */ @@ -2428,8 +2428,8 @@ static int ata_promise_new_dmastart(device_t dev) { - struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev)); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); if (ch->flags & ATA_48BIT_ACTIVE) { ATA_OUTB(ctlr->r_res1, 0x11, @@ -2451,8 +2451,8 @@ static int ata_promise_new_dmastop(device_t dev) { - struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev)); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); int error; if (ch->flags & ATA_48BIT_ACTIVE) { ==== //depot/projects/wifi/sys/dev/ata/ata-dma.c#6 (text+ko) ==== @@ -27,7 +27,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/ata/ata-dma.c,v 1.135 2005/04/30 16:22:07 sos Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/ata/ata-dma.c,v 1.136 2005/05/01 12:24:45 sos Exp $"); #include #include @@ -218,7 +218,7 @@ static int ata_dmaload(device_t dev, caddr_t data, int32_t count, int dir) { - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); struct ata_dmasetprd_args cba; if (ch->dma->flags & ATA_DMA_LOADED) { @@ -259,7 +259,7 @@ int ata_dmaunload(device_t dev) { - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); bus_dmamap_sync(ch->dma->sg_tag, ch->dma->sg_map, BUS_DMASYNC_POSTWRITE); bus_dmamap_sync(ch->dma->data_tag, ch->dma->data_map, ==== //depot/projects/wifi/sys/dev/ata/ata-lowlevel.c#11 (text+ko) ==== @@ -27,7 +27,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/ata/ata-lowlevel.c,v 1.64 2005/04/30 16:22:07 sos Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/ata/ata-lowlevel.c,v 1.65 2005/05/01 12:24:45 sos Exp $"); #include "opt_ata.h" #include @@ -129,7 +129,7 @@ /* ATA DMA data transfer commands */ case ATA_R_DMA: /* check sanity, setup SG list and DMA engine */ - if (ch->dma->load(request->dev, request->data, request->bytecount, + if (ch->dma->load(ch->dev, request->data, request->bytecount, request->flags & ATA_R_READ)) { device_printf(request->dev, "setting up DMA failed\n"); request->result = EIO; @@ -147,7 +147,7 @@ } /* start DMA engine */ - if (ch->dma->start(request->dev)) { + if (ch->dma->start(ch->dev)) { device_printf(request->dev, "error starting DMA\n"); request->result = EIO; goto begin_finished; @@ -218,7 +218,7 @@ } /* check sanity, setup SG list and DMA engine */ - if (ch->dma->load(request->dev, request->data, request->bytecount, + if (ch->dma->load(ch->dev, request->data, request->bytecount, request->flags & ATA_R_READ)) { device_printf(request->dev, "setting up DMA failed\n"); request->result = EIO; @@ -261,7 +261,7 @@ ATA_PROTO_ATAPI_12 ? 6 : 8); /* start DMA engine */ - if (ch->dma->start(request->dev)) { + if (ch->dma->start(ch->dev)) { request->result = EIO; goto begin_finished; } @@ -272,7 +272,7 @@ begin_finished: if (ch->dma && ch->dma->flags & ATA_DMA_LOADED) - ch->dma->unload(request->dev); + ch->dma->unload(ch->dev); return ATA_OP_FINISHED; begin_continue: @@ -390,7 +390,7 @@ /* stop DMA engine and get status */ if (ch->dma->stop) - request->dmastat = ch->dma->stop(request->dev); + request->dmastat = ch->dma->stop(ch->dev); /* did we get error or data */ if (request->status & ATA_S_ERROR) @@ -401,7 +401,7 @@ request->donecount = request->bytecount; /* release SG list etc */ - ch->dma->unload(request->dev); + ch->dma->unload(ch->dev); /* done with HW */ goto end_finished; @@ -502,7 +502,7 @@ /* stop the engine and get engine status */ if (ch->dma->stop) - request->dmastat = ch->dma->stop(request->dev); + request->dmastat = ch->dma->stop(ch->dev); /* did we get error or data */ if (request->status & (ATA_S_ERROR | ATA_S_DWF)) @@ -513,7 +513,7 @@ request->donecount = request->bytecount; /* release SG list etc */ - ch->dma->unload(request->dev); + ch->dma->unload(ch->dev); /* done with HW */ goto end_finished; ==== //depot/projects/wifi/sys/dev/ata/ata-pci.c#7 (text+ko) ==== @@ -27,7 +27,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/ata/ata-pci.c,v 1.101 2005/04/30 16:22:07 sos Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/ata/ata-pci.c,v 1.102 2005/05/01 12:24:45 sos Exp $"); #include "opt_ata.h" #include @@ -419,7 +419,7 @@ static int ata_pci_dmastart(device_t dev) { - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); @@ -435,7 +435,7 @@ static int ata_pci_dmastop(device_t dev) { - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); int error; ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, ==== //depot/projects/wifi/sys/dev/ata/ata-raid.h#6 (text+ko) ==== @@ -25,7 +25,7 @@ * (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: src/sys/dev/ata/ata-raid.h,v 1.32 2005/04/30 16:22:07 sos Exp $ + * $FreeBSD: src/sys/dev/ata/ata-raid.h,v 1.33 2005/05/01 08:45:12 sos Exp $ */ /* misc defines */ @@ -522,7 +522,7 @@ /* Promise FastTrak Metadata */ #define PR_LBA(dev) \ - (((struct ad_softc *)device_get_ivars(dev))->total_secs - 63) + (((((struct ad_softc *)device_get_ivars(dev))->total_secs / (((struct ad_softc *)device_get_ivars(dev))->heads * ((struct ad_softc *)device_get_ivars(dev))->sectors)) * ((struct ad_softc *)device_get_ivars(dev))->heads * ((struct ad_softc *)device_get_ivars(dev))->sectors) - ((struct ad_softc *)device_get_ivars(dev))->sectors) struct promise_raid_conf { char promise_id[24]; ==== //depot/projects/wifi/sys/dev/hwpmc/hwpmc_amd.c#2 (text+ko) ==== @@ -26,7 +26,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/hwpmc/hwpmc_amd.c,v 1.4 2005/04/28 08:13:18 jkoshy Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/hwpmc/hwpmc_amd.c,v 1.5 2005/05/01 14:11:48 jkoshy Exp $"); /* Support for the AMD K7 and later processors */ @@ -360,7 +360,7 @@ ("[amd,%d] No owner for HWPMC [cpu%d,pmc%d]", __LINE__, cpu, ri)); - mode = pm->pm_mode; + mode = PMC_TO_MODE(pm); PMCDBG(MDP,REA,1,"amd-read id=%d class=%d", ri, pd->pm_descr.pd_class); @@ -413,7 +413,7 @@ ("[amd,%d] PMC not owned (cpu%d,pmc%d)", __LINE__, cpu, ri)); - mode = pm->pm_mode; + mode = PMC_TO_MODE(pm); if (pd->pm_descr.pd_class == PMC_CLASS_TSC) return 0; @@ -461,6 +461,18 @@ } /* + * Retrieve a configured PMC pointer from hardware state. + */ + +static int +amd_get_config(int cpu, int ri, struct pmc **ppm) +{ + *ppm = pmc_pcpu[cpu]->pc_hwpmcs[ri]->phw_pmc; + + return 0; +} + +/* * Machine dependent actions taken during the context switch in of a * thread. */ @@ -471,10 +483,10 @@ (void) pc; PMCDBG(MDP,SWI,1, "pc=%p pp=%p enable-msr=%d", pc, pp, - (pp->pp_flags & PMC_FLAG_ENABLE_MSR_ACCESS) != 0); + (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS) != 0); /* enable the RDPMC instruction if needed */ - if (pp->pp_flags & PMC_FLAG_ENABLE_MSR_ACCESS) + if (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS) load_cr4(rcr4() | CR4_PCE); return 0; @@ -492,7 +504,7 @@ (void) pp; /* can be NULL */ PMCDBG(MDP,SWO,1, "pc=%p pp=%p enable-msr=%d", pc, pp, pp ? - (pp->pp_flags & PMC_FLAG_ENABLE_MSR_ACCESS) == 1 : 0); + (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS) == 1 : 0); /* always turn off the RDPMC instruction */ load_cr4(rcr4() & ~CR4_PCE); @@ -523,7 +535,7 @@ pd = &amd_pmcdesc[ri].pm_descr; /* check class match */ - if (pd->pd_class != pm->pm_class) + if (pd->pd_class != a->pm_class) return EINVAL; caps = pm->pm_caps; @@ -765,7 +777,7 @@ continue; } - mode = pm->pm_mode; + mode = PMC_TO_MODE(pm); if (PMC_IS_SAMPLING_MODE(mode) && AMD_PMC_HAS_OVERFLOWED(perfctr)) { atomic_add_int(&pmc_stats.pm_intr_processed, 1); @@ -803,8 +815,6 @@ return error; pi->pm_class = pd->pm_descr.pd_class; - pi->pm_caps = pd->pm_descr.pd_caps; - pi->pm_width = pd->pm_descr.pd_width; if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { pi->pm_enabled = TRUE; @@ -982,8 +992,17 @@ /* this processor has two classes of usable PMCs */ pmc_mdep->pmd_nclass = 2; - pmc_mdep->pmd_classes[0] = PMC_CLASS_TSC; - pmc_mdep->pmd_classes[1] = AMD_PMC_CLASS; + + /* TSC */ + pmc_mdep->pmd_classes[0].pm_class = PMC_CLASS_TSC; + pmc_mdep->pmd_classes[0].pm_caps = PMC_CAP_READ; + pmc_mdep->pmd_classes[0].pm_width = 64; + + /* AMD K7/K8 PMCs */ + pmc_mdep->pmd_classes[1].pm_class = AMD_PMC_CLASS; + pmc_mdep->pmd_classes[1].pm_caps = AMD_PMC_CAPS; + pmc_mdep->pmd_classes[1].pm_width = 48; + pmc_mdep->pmd_nclasspmcs[0] = 1; pmc_mdep->pmd_nclasspmcs[1] = (AMD_NPMCS-1); @@ -994,6 +1013,7 @@ pmc_mdep->pmd_read_pmc = amd_read_pmc; pmc_mdep->pmd_write_pmc = amd_write_pmc; pmc_mdep->pmd_config_pmc = amd_config_pmc; + pmc_mdep->pmd_get_config = amd_get_config; pmc_mdep->pmd_allocate_pmc = amd_allocate_pmc; pmc_mdep->pmd_release_pmc = amd_release_pmc; pmc_mdep->pmd_start_pmc = amd_start_pmc; ==== //depot/projects/wifi/sys/dev/hwpmc/hwpmc_intel.c#2 (text+ko) ==== @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/hwpmc/hwpmc_intel.c,v 1.3 2005/04/27 05:51:13 jkoshy Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/hwpmc/hwpmc_intel.c,v 1.4 2005/05/01 14:11:48 jkoshy Exp $"); #include #include @@ -92,7 +92,9 @@ pmc_mdep->pmd_cputype = cputype; pmc_mdep->pmd_nclass = 2; - pmc_mdep->pmd_classes[0] = PMC_CLASS_TSC; + pmc_mdep->pmd_classes[0].pm_class = PMC_CLASS_TSC; + pmc_mdep->pmd_classes[0].pm_caps = PMC_CAP_READ; + pmc_mdep->pmd_classes[0].pm_width = 64; pmc_mdep->pmd_nclasspmcs[0] = 1; error = 0; ==== //depot/projects/wifi/sys/dev/hwpmc/hwpmc_mod.c#2 (text+ko) ==== @@ -26,7 +26,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/hwpmc/hwpmc_mod.c,v 1.6 2005/04/28 08:13:18 jkoshy Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/hwpmc/hwpmc_mod.c,v 1.7 2005/05/01 14:11:48 jkoshy Exp $"); #include #include @@ -151,12 +151,14 @@ static struct pmc *pmc_find_pmc_descriptor_in_process(struct pmc_owner *po, pmc_id_t pmc); static void pmc_release_pmc_descriptor(struct pmc *pmc); -static int pmc_can_allocate_rowindex(struct proc *p, unsigned int ri); +static int pmc_can_allocate_rowindex(struct proc *p, unsigned int ri, + int cpu); static struct pmc_process *pmc_find_process_descriptor(struct proc *p, uint32_t mode); static void pmc_remove_process_descriptor(struct pmc_process *pp); static struct pmc_owner *pmc_find_owner_descriptor(struct proc *p); static int pmc_find_pmc(pmc_id_t pmcid, struct pmc **pm); +static void pmc_force_context_switch(void); static void pmc_remove_owner(struct pmc_owner *po); static void pmc_maybe_remove_owner(struct pmc_owner *po); static void pmc_unlink_target_process(struct pmc *pmc, @@ -364,6 +366,7 @@ CMP_SET_FLAG_MIN("cfg", CFG); CMP_SET_FLAG_MIN("sta", STA); CMP_SET_FLAG_MIN("sto", STO); + CMP_SET_FLAG_MIN("int", INT); CMP_SET_FLAG_MIN("bnd", BND); CMP_SET_FLAG_MIN("sel", SEL); else /* unrecognized keyword */ @@ -573,6 +576,27 @@ } /* + * Force a context switch. + * + * We do this by tsleep'ing for 1 tick -- invoking mi_switch() is not + * guaranteed to force a context switch. + */ + +static void +pmc_force_context_switch(void) +{ + u_char curpri; + + mtx_lock_spin(&sched_lock); + curpri = curthread->td_priority; + mtx_unlock_spin(&sched_lock); + + (void) tsleep((void *) pmc_force_context_switch, curpri, + "pmcctx", 1); + +} + +/* * Update the per-pmc histogram */ @@ -671,7 +695,7 @@ * XXX rework needed. */ - if (po->po_flags & PMC_FLAG_OWNS_LOGFILE) + if (po->po_flags & PMC_PO_OWNS_LOGFILE) pmc_configure_log(po, -1); } @@ -693,7 +717,7 @@ */ if (LIST_EMPTY(&po->po_pmcs) && - ((po->po_flags & PMC_FLAG_OWNS_LOGFILE) == 0)) { + ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)) { pmc_remove_owner(po); FREE(po, M_PMC); } @@ -718,7 +742,7 @@ ("[pmc,%d] Illegal reference count %d for process record %p", __LINE__, pp->pp_refcnt, (void *) pp)); - ri = pm->pm_rowindex; + ri = PMC_TO_ROWINDEX(pm); PMCDBG(PRC,TLK,1, "link-target pmc=%p ri=%d pmc-process=%p", pm, ri, pp); @@ -740,12 +764,10 @@ atomic_store_rel_ptr(&pp->pp_pmcs[ri].pp_pmc, pm); if (pm->pm_owner->po_owner == pp->pp_proc) - pp->pp_flags |= PMC_FLAG_ENABLE_MSR_ACCESS; + pm->pm_flags |= PMC_F_ATTACHED_TO_OWNER; pp->pp_refcnt++; - PMCDBG(PRC,TLK,2, "enable-msr %d", - (pp->pp_flags & PMC_FLAG_ENABLE_MSR_ACCESS) != 0); } /* @@ -767,7 +789,7 @@ ("[pmc,%d] Illegal ref count %d on process record %p", __LINE__, pp->pp_refcnt, (void *) pp)); - ri = pm->pm_rowindex; + ri = PMC_TO_ROWINDEX(pm); PMCDBG(PRC,TUL,1, "unlink-target pmc=%p ri=%d pmc-process=%p", pm, ri, pp); @@ -779,8 +801,11 @@ pp->pp_pmcs[ri].pp_pmc = NULL; pp->pp_pmcs[ri].pp_pmcval = (pmc_value_t) 0; - if (pm->pm_owner->po_owner == pp->pp_proc) - pp->pp_flags &= ~PMC_FLAG_ENABLE_MSR_ACCESS; + /* Remove owner-specific flags */ + if (pm->pm_owner->po_owner == pp->pp_proc) { + pp->pp_flags &= ~PMC_PP_ENABLE_MSR_ACCESS; + pm->pm_flags &= ~PMC_F_ATTACHED_TO_OWNER; + } pp->pp_refcnt--; @@ -792,9 +817,6 @@ KASSERT(ptgt != NULL, ("[pmc,%d] process %p (pp: %p) not found " "in pmc %p", __LINE__, pp->pp_proc, pp, pm)); - PMCDBG(PRC,TUL,4, "unlink ptgt=%p, enable-msr=%d", ptgt, - (pp->pp_flags & PMC_FLAG_ENABLE_MSR_ACCESS) != 0); - LIST_REMOVE(ptgt, pt_next); FREE(ptgt, M_PMC); } @@ -897,7 +919,7 @@ sx_assert(&pmc_sx, SX_XLOCKED); PMCDBG(PRC,ATT,2, "attach-one pm=%p ri=%d proc=%p (%d, %s)", pm, - pm->pm_rowindex, p, p->p_pid, p->p_comm); + PMC_TO_ROWINDEX(pm), p, p->p_pid, p->p_comm); /* * Locate the process descriptor corresponding to process 'p', @@ -910,7 +932,7 @@ * process descriptor and PMC. */ - ri = pm->pm_rowindex; + ri = PMC_TO_ROWINDEX(pm); if ((pp = pmc_find_process_descriptor(p, PMC_FLAG_ALLOCATE)) == NULL) return ENOMEM; @@ -944,7 +966,16 @@ sx_assert(&pmc_sx, SX_XLOCKED); PMCDBG(PRC,ATT,1, "attach pm=%p ri=%d proc=%p (%d, %s)", pm, - pm->pm_rowindex, p, p->p_pid, p->p_comm); + PMC_TO_ROWINDEX(pm), p, p->p_pid, p->p_comm); + + + /* + * If this PMC successfully allowed a GETMSR operation + * in the past, disallow further ATTACHes. + */ + + if ((pm->pm_flags & PMC_PP_ENABLE_MSR_ACCESS) != 0) + return EPERM; if ((pm->pm_flags & PMC_F_DESCENDANTS) == 0) return pmc_attach_one_process(p, pm); @@ -999,11 +1030,11 @@ KASSERT(pm != NULL, ("[pmc,%d] null pm pointer", __LINE__)); + ri = PMC_TO_ROWINDEX(pm); + PMCDBG(PRC,ATT,2, "detach-one pm=%p ri=%d proc=%p (%d, %s) flags=0x%x", - pm, pm->pm_rowindex, p, p->p_pid, p->p_comm, flags); + pm, ri, p, p->p_pid, p->p_comm, flags); - ri = pm->pm_rowindex; - if ((pp = pmc_find_process_descriptor(p, 0)) == NULL) return ESRCH; @@ -1049,7 +1080,7 @@ sx_assert(&pmc_sx, SX_XLOCKED); PMCDBG(PRC,ATT,1, "detach pm=%p ri=%d proc=%p (%d, %s)", pm, - pm->pm_rowindex, p, p->p_pid, p->p_comm); + PMC_TO_ROWINDEX(pm), p, p->p_pid, p->p_comm); if ((pm->pm_flags & PMC_F_DESCENDANTS) == 0) return pmc_detach_one_process(p, pm, PMC_FLAG_REMOVE); @@ -1131,7 +1162,6 @@ int cpu; unsigned int ri; struct pmc *pm; - struct pmc_hw *phw; struct pmc_process *pp; struct pmc_owner *po; struct proc *p; @@ -1183,22 +1213,22 @@ * state similar to the CSW_OUT code. */ - phw = pmc_pcpu[cpu]->pc_hwpmcs[ri]; - pm = phw->phw_pmc; + pm = NULL; + (void) (*md->pmd_get_config)(cpu, ri, &pm); PMCDBG(PRC,EXT,2, "ri=%d pm=%p", ri, pm); if (pm == NULL || - !PMC_IS_VIRTUAL_MODE(pm->pm_mode)) + !PMC_IS_VIRTUAL_MODE(PMC_TO_MODE(pm))) continue; PMCDBG(PRC,EXT,2, "ppmcs[%d]=%p pm=%p " "state=%d", ri, pp->pp_pmcs[ri].pp_pmc, pm, pm->pm_state); - KASSERT(pm->pm_rowindex == ri, + KASSERT(PMC_TO_ROWINDEX(pm) == ri, ("[pmc,%d] ri mismatch pmc(%d) ri(%d)", - __LINE__, pm->pm_rowindex, ri)); + __LINE__, PMC_TO_ROWINDEX(pm), ri)); KASSERT(pm == pp->pp_pmcs[ri].pp_pmc, ("[pmc,%d] pm %p != pp_pmcs[%d] %p", @@ -1222,10 +1252,11 @@ mtx_pool_unlock_spin(pmc_mtxpool, pm); } + atomic_subtract_rel_32(&pm->pm_runcount,1); + KASSERT((int) pm->pm_runcount >= 0, ("[pmc,%d] runcount is %d", __LINE__, ri)); - atomic_subtract_rel_32(&pm->pm_runcount,1); (void) md->pmd_config_pmc(cpu, ri, NULL); } @@ -1254,6 +1285,7 @@ FREE(pp, M_PMC); + } else critical_exit(); /* pp == NULL */ @@ -1445,13 +1477,13 @@ if ((pm = pp->pp_pmcs[ri].pp_pmc) == NULL) continue; - KASSERT(PMC_IS_VIRTUAL_MODE(pm->pm_mode), + KASSERT(PMC_IS_VIRTUAL_MODE(PMC_TO_MODE(pm)), ("[pmc,%d] Target PMC in non-virtual mode (%d)", - __LINE__, pm->pm_mode)); + __LINE__, PMC_TO_MODE(pm))); - KASSERT(pm->pm_rowindex == ri, + KASSERT(PMC_TO_ROWINDEX(pm) == ri, ("[pmc,%d] Row index mismatch pmc %d != ri %d", - __LINE__, pm->pm_rowindex, ri)); + __LINE__, PMC_TO_ROWINDEX(pm), ri)); /* * Only PMCs that are marked as 'RUNNING' need @@ -1510,7 +1542,6 @@ struct pmc *pm; struct proc *p; struct pmc_cpu *pc; - struct pmc_hw *phw; struct pmc_process *pp; pmc_value_t newvalue, tmp; @@ -1560,18 +1591,18 @@ for (ri = 0; ri < md->pmd_npmc; ri++) { - phw = pc->pc_hwpmcs[ri]; - pm = phw->phw_pmc; + pm = NULL; + (void) (*md->pmd_get_config)(cpu, ri, &pm); if (pm == NULL) /* nothing at this row index */ continue; - if (!PMC_IS_VIRTUAL_MODE(pm->pm_mode)) + if (!PMC_IS_VIRTUAL_MODE(PMC_TO_MODE(pm))) continue; /* not a process virtual PMC */ - KASSERT(pm->pm_rowindex == ri, + KASSERT(PMC_TO_ROWINDEX(pm) == ri, ("[pmc,%d] ri mismatch pmc(%d) ri(%d)", - __LINE__, pm->pm_rowindex, ri)); + __LINE__, PMC_TO_ROWINDEX(pm), ri)); /* Stop hardware */ md->pmd_stop_pmc(cpu, ri); @@ -1838,7 +1869,7 @@ volatile int maxloop; #endif u_int ri, cpu; - u_char curpri; + enum pmc_mode mode; struct pmc_hw *phw; struct pmc_process *pp; struct pmc_target *ptgt, *tmp; @@ -1848,16 +1879,17 @@ KASSERT(pm, ("[pmc,%d] null pmc", __LINE__)); - ri = pm->pm_rowindex; + ri = PMC_TO_ROWINDEX(pm); + mode = PMC_TO_MODE(pm); PMCDBG(PMC,REL,1, "release-pmc pmc=%p ri=%d mode=%d", pm, ri, - pm->pm_mode); + mode); /* * First, we take the PMC off hardware. */ cpu = 0; - if (PMC_IS_SYSTEM_MODE(pm->pm_mode)) { + if (PMC_IS_SYSTEM_MODE(mode)) { /* * A system mode PMC runs on a specific CPU. Switch @@ -1866,7 +1898,7 @@ pmc_save_cpu_binding(&pb); - cpu = pm->pm_gv.pm_cpu; + cpu = PMC_TO_CPU(pm); if (pm->pm_state == PMC_STATE_RUNNING) { @@ -1895,7 +1927,7 @@ pmc_restore_cpu_binding(&pb); - } else if (PMC_IS_VIRTUAL_MODE(pm->pm_mode)) { + } else if (PMC_IS_VIRTUAL_MODE(mode)) { /* * A virtual PMC could be running on multiple CPUs at @@ -1924,17 +1956,11 @@ maxloop--; KASSERT(maxloop > 0, ("[pmc,%d] (ri%d, rc%d) waiting too long for " - "pmc to be free", __LINE__, pm->pm_rowindex, - pm->pm_runcount)); + "pmc to be free", __LINE__, + PMC_TO_ROWINDEX(pm), pm->pm_runcount)); #endif - mtx_lock_spin(&sched_lock); - curpri = curthread->td_priority; - mtx_unlock_spin(&sched_lock); - - (void) tsleep((void *) pmc_release_pmc_descriptor, - curpri, "pmcrel", 1); - + pmc_force_context_switch(); } /* @@ -1977,7 +2003,7 @@ * Update row disposition */ - if (PMC_IS_SYSTEM_MODE(pm->pm_mode)) + if (PMC_IS_SYSTEM_MODE(PMC_TO_MODE(pm))) PMC_UNMARK_ROW_STANDALONE(ri); else PMC_UNMARK_ROW_THREAD(ri); @@ -2007,21 +2033,20 @@ if (pl == NULL) return ENOMEM; - if ((po = pmc_find_owner_descriptor(p)) == NULL) { + if ((po = pmc_find_owner_descriptor(p)) == NULL) if ((po = pmc_allocate_owner_descriptor(p)) == NULL) { FREE(pl, M_PMC); return ENOMEM; } - po->po_flags |= PMC_FLAG_IS_OWNER; /* real owner */ - } - if (pmc->pm_mode == PMC_MODE_TS) { + /* XXX is this too restrictive */ + if (PMC_ID_TO_MODE(pmc->pm_id) == PMC_MODE_TS) { /* can have only one TS mode PMC per process */ - if (po->po_flags & PMC_FLAG_HAS_TS_PMC) { + if (po->po_flags & PMC_PO_HAS_TS_PMC) { FREE(pl, M_PMC); return EINVAL; } - po->po_flags |= PMC_FLAG_HAS_TS_PMC; + po->po_flags |= PMC_PO_HAS_TS_PMC; } KASSERT(pmc->pm_owner == NULL, @@ -2067,22 +2092,41 @@ */ static int -pmc_can_allocate_rowindex(struct proc *p, unsigned int ri) +pmc_can_allocate_rowindex(struct proc *p, unsigned int ri, int cpu) { + enum pmc_mode mode; + struct pmc *pm; struct pmc_list *pl; struct pmc_owner *po; struct pmc_process *pp; - PMCDBG(PMC,ALR,1, "can-allocate-rowindex proc=%p (%d, %s) ri=%d", - p, p->p_pid, p->p_comm, ri); + PMCDBG(PMC,ALR,1, "can-allocate-rowindex proc=%p (%d, %s) ri=%d " + "cpu=%d", p, p->p_pid, p->p_comm, ri, cpu); - /* we shouldn't have allocated a PMC at row index 'ri' */ + /* + * We shouldn't have already allocated a process-mode PMC at + * row index 'ri'. + * + * We shouldn't have allocated a system-wide PMC on the same + * CPU and same RI. + */ if ((po = pmc_find_owner_descriptor(p)) != NULL) - LIST_FOREACH(pl, &po->po_pmcs, pl_next) - if (pl->pl_pmc->pm_rowindex == ri) - return EEXIST; + LIST_FOREACH(pl, &po->po_pmcs, pl_next) { + pm = pl->pl_pmc; + if (PMC_TO_ROWINDEX(pm) == ri) { + mode = PMC_TO_MODE(pm); + if (PMC_IS_VIRTUAL_MODE(mode)) + return EEXIST; + if (PMC_IS_SYSTEM_MODE(mode) && + (int) PMC_TO_CPU(pm) == cpu) + return EEXIST; + } + } - /* we shouldn't be the target of any PMC ourselves at this index */ + /* + * We also shouldn't be the target of any PMC at this index + * since otherwise a PMC_ATTACH to ourselves will fail. + */ if ((pp = pmc_find_process_descriptor(p, 0)) != NULL) if (pp->pp_pmcs[ri].pp_pmc) return EEXIST; @@ -2139,7 +2183,7 @@ } /* - * Find a PMC descriptor with user handle 'pmc' for thread 'td'. + * Find a PMC descriptor with user handle 'pmcid' for thread 'td'. */ static struct pmc * @@ -2147,12 +2191,12 @@ { struct pmc_list *pl; - KASSERT(pmcid < md->pmd_npmc, - ("[pmc,%d] Illegal pmc index %d (max %d)", __LINE__, pmcid, - md->pmd_npmc)); + KASSERT(PMC_ID_TO_ROWINDEX(pmcid) < md->pmd_npmc, + ("[pmc,%d] Illegal pmc index %d (max %d)", __LINE__, + PMC_ID_TO_ROWINDEX(pmcid), md->pmd_npmc)); LIST_FOREACH(pl, &po->po_pmcs, pl_next) - if (pl->pl_pmc->pm_rowindex == pmcid) + if (pl->pl_pmc->pm_id == pmcid) return pl->pl_pmc; return NULL; @@ -2187,17 +2231,21 @@ pmc_start(struct pmc *pm) { int error, cpu, ri; + enum pmc_mode mode; struct pmc_binding pb; KASSERT(pm != NULL, ("[pmc,%d] null pm", __LINE__)); - PMCDBG(PMC,OPS,1, "start pmc=%p mode=%d ri=%d", pm, pm->pm_mode, - pm->pm_rowindex); + mode = PMC_TO_MODE(pm); + ri = PMC_TO_ROWINDEX(pm); + error = 0; + + PMCDBG(PMC,OPS,1, "start pmc=%p mode=%d ri=%d", pm, mode, ri); pm->pm_state = PMC_STATE_RUNNING; - if (PMC_IS_VIRTUAL_MODE(pm->pm_mode)) { + if (PMC_IS_VIRTUAL_MODE(mode)) { /* * If a PMCATTACH hadn't been done on this @@ -2205,32 +2253,36 @@ */ if (LIST_EMPTY(&pm->pm_targets)) - return pmc_attach_process(pm->pm_owner->po_owner, pm); + error = pmc_attach_process(pm->pm_owner->po_owner, pm); + /* + * If the PMC is attached to its owner, then force a context + * switch to ensure that the MD state gets set correctly. + */ + if (error == 0 && (pm->pm_flags & PMC_F_ATTACHED_TO_OWNER)) + pmc_force_context_switch(); /* * Nothing further to be done; thread context switch code - * will start/stop the PMC as appropriate. + * will start/stop the hardware as appropriate. */ - return 0; + return error; } /* - * A system-mode PMC. Move to the CPU associated with this + * A system-wide PMC. Move to the CPU associated with this * PMC, and start the hardware. */ pmc_save_cpu_binding(&pb); - cpu = pm->pm_gv.pm_cpu; + cpu = PMC_TO_CPU(pm); if (pmc_cpu_is_disabled(cpu)) return ENXIO; - ri = pm->pm_rowindex; - pmc_select_cpu(cpu); /* @@ -2238,11 +2290,13 @@ * so write out the initial value and start the PMC. */ + critical_enter(); if ((error = md->pmd_write_pmc(cpu, ri, - PMC_IS_SAMPLING_MODE(pm->pm_mode) ? + PMC_IS_SAMPLING_MODE(mode) ? pm->pm_sc.pm_reloadcount : pm->pm_sc.pm_initial)) == 0) error = md->pmd_start_pmc(cpu, ri); + critical_exit(); pmc_restore_cpu_binding(&pb); @@ -2256,13 +2310,13 @@ static int pmc_stop(struct pmc *pm) { >>> TRUNCATED FOR MAIL (1000 lines) <<<