Package org.jnode.vm.x86.performance

Source Code of org.jnode.vm.x86.performance.P4FamilyPerformanceCounters$P4Event

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.vm.x86.performance;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.jnode.vm.performance.PerformanceCounterEvent;
import org.jnode.vm.performance.PresetEvent;
import org.jnode.vm.x86.MSR;
import org.jnode.vm.x86.VmX86Processor;
import org.jnode.vm.x86.VmX86Thread;

abstract class P4FamilyPerformanceCounters extends X86PerformanceCounters {

    private final CounterMSRInfo[] counters;

    private final P4Event[] events;

    private final Set<PerformanceCounterEvent> eventSet;

    // ------------------------------------------
    // ESCR MSR indexes
    // ------------------------------------------  
    public static final int BPU_ESCR0 = 0x3B2;
    public static final int BPU_ESCR1 = 0x3B3;
    public static final int BSU_ESCR0 = 0x3A0;
    public static final int BSU_ESCR1 = 0x3A1;
    public static final int CR_ESCR0 = 0;
    public static final int CR_ESCR1 = 0;
    public static final int CRU_ESCR0 = 0x3B8;
    public static final int CRU_ESCR1 = 0x3B9;
    public static final int CRU_ESCR2 = 0x3CC;
    public static final int CRU_ESCR3 = 0x3CD;
    public static final int CRU_ESCR4 = 0x3E0;
    public static final int CRU_ESCR5 = 0x3E1;
    public static final int FSB_ESCR0 = 0x3A2;
    public static final int FSB_ESCR1 = 0x3A3;
    public static final int IS_ESCR0 = 0x3B4;
    public static final int IS_ESCR1 = 0x3B5;
    public static final int ITLB_ESCR0 = 0x3B6;
    public static final int ITLB_ESCR1 = 0x3B7;
    public static final int IX_ESCR0 = 0x3C8;
    public static final int IX_ESCR1 = 0x3C9;
    public static final int MOP_ESCR0 = 0x3AA;
    public static final int MOP_ESCR1 = 0x3AB;
    public static final int MS_ESCR0 = 0x3C0;
    public static final int MS_ESCR1 = 0x3C1;
    public static final int PMH_ESCR1 = 0x3AD;
    public static final int PMH_ESCR0 = 0x3AC;
    public static final int TBPU_ESCR0 = 0x3C2;
    public static final int TBPU_ESCR1 = 0x3C3;
    public static final int TC_ESCR0 = 0x3C4;
    public static final int TC_ESCR1 = 0x3C5;

    /**
     * @param cpu
     * @param maxCounters
     */
    public P4FamilyPerformanceCounters(VmX86Processor cpu,
                                       CounterMSRInfo[] counters, P4Event[] events) {
        super(cpu, counters.length);
        this.counters = counters;
        this.events = events;
        this.eventSet = Collections
            .unmodifiableSet(new TreeSet<PerformanceCounterEvent>(Arrays
                .asList(events)));
    }

    /**
     * Class holding MSR information for a single performance counter.
     *
     * @author Ewout Prangsma (epr@users.sourceforge.net)
     */
    public static class CounterMSRInfo {
        final char counterMSRIndex;

        final char cccrMSRIndex;

        /**
         * @param counterMSRIndex
         * @param cccrMSRIndex
         * @param escrNrs
         * @param escrMSRIndexes
         */
        public CounterMSRInfo(int counterMSRIndex, int cccrMSRIndex) {
            this.counterMSRIndex = (char) counterMSRIndex;
            this.cccrMSRIndex = (char) cccrMSRIndex;
        }
    }

    /**
     * ESCR restriction.
     *
     * @author Ewout Prangsma (epr@users.sourceforge.net)
     */
    public static final class ESCR_RES {
        /**
         * The ESCR MSR index
         */
        final char escr;

        /**
         * The Counters number (0..17) to which this event is restricted
         */
        final byte[] counters;

        /**
         * @param escr
         * @param counters
         */
        public ESCR_RES(int escr, byte[] counters) {
            this.escr = (char) escr;
            this.counters = counters;
        }

        /**
         * @param escr
         * @param cnt0
         */
        public ESCR_RES(int escr, int cnt0) {
            this(escr, new byte[]{(byte) cnt0});
        }

        /**
         * @param escr
         * @param cnt0
         * @param cnt1
         */
        public ESCR_RES(int escr, int cnt0, int cnt1) {
            this(escr, new byte[]{(byte) cnt0, (byte) cnt1});
        }

        /**
         * @param escr
         * @param cnt0
         * @param cnt1
         * @param cnt2
         */
        public ESCR_RES(int escr, int cnt0, int cnt1, int cnt2) {
            this(escr, new byte[]{(byte) cnt0, (byte) cnt1, (byte) cnt2});
        }
    }

    /**
     * Event class for P4 familiy events.
     *
     * @author Ewout Prangsma (epr@users.sourceforge.net)
     */
    public static final class P4Event extends PerformanceCounterEvent {

        /**
         * ESCR bits 30-25
         */
        private final byte escrEventSelect;

        /**
         * ESCR bits 24-9
         */
        private final char escrEventMask;

        /**
         * ESCR restrictions
         */
        private final ESCR_RES[] escrRestr;

        /**
         * CCCR select value
         */
        private final byte cccrSelect;

        /**
         * @param preset
         */
        public P4Event(PresetEvent preset, int escrEventSelect,
                       int escrEventMask, int cccrSelect, ESCR_RES res0) {
            this(preset, escrEventSelect, escrEventMask, cccrSelect,
                new ESCR_RES[]{res0});
        }

        /**
         * @param preset
         */
        public P4Event(PresetEvent preset, int escrEventSelect,
                       int escrEventMask, int cccrSelect, ESCR_RES res0, ESCR_RES res1) {
            this(preset, escrEventSelect, escrEventMask, cccrSelect,
                new ESCR_RES[]{res0, res1});
        }

        /**
         * @param preset
         */
        public P4Event(PresetEvent preset, int escrEventSelect,
                       int escrEventMask, int cccrSelect, ESCR_RES[] ress) {
            super(preset);
            this.escrEventSelect = (byte) escrEventSelect;
            this.escrEventMask = (char) escrEventMask;
            this.cccrSelect = (byte) cccrSelect;
            this.escrRestr = ress;
        }

        /**
         * @param id
         * @param description
         */
        public P4Event(String id, String description, int escrEventSelect,
                       int escrEventMask, int cccrSelect, ESCR_RES[] ress) {
            super(id, description);
            this.escrEventSelect = (byte) escrEventSelect;
            this.escrEventMask = (char) escrEventMask;
            this.cccrSelect = (byte) cccrSelect;
            this.escrRestr = ress;
        }

        /**
         * Creates the value for the ESCR MSR.
         *
         * @return
         */
        final long createESCRValue() {
            // USR | eventMask | eventSelect
            return (1 << 2) | (escrEventMask << 9) | (escrEventSelect << 25);
        }

        /**
         * Creates the value for the CCCR MSR.
         *
         * @return
         */
        final long createCCCRValue() {
            // EN | ESCR select | Rsvd
            return (1 << 12) | (cccrSelect << 13) | (3 << 16);
        }
    }

    /**
     * @see org.jnode.vm.x86.performance.X86PerformanceCounters#getAvailableEvent(java.lang.String)
     */
    public final PerformanceCounterEvent getAvailableEvent(String id) {
        for (PerformanceCounterEvent e : events) {
            if (e.getId().equals(id)) {
                return e;
            }
        }
        return null;
    }

    /**
     * @see org.jnode.vm.x86.performance.X86PerformanceCounters#getAvailableEvents()
     */
    public final Set<PerformanceCounterEvent> getAvailableEvents() {
        return eventSet;
    }

    /**
     * @see org.jnode.vm.x86.performance.X86PerformanceCounters#getCounterValues(long[],
     *      org.jnode.vm.x86.VmX86Thread)
     */
    protected void getCounterValues(long[] counters, VmX86Thread thread) {
        final MSR[] countMSRs = thread.getReadWriteMSRs();
        if (countMSRs == null) {
            throw new IllegalArgumentException("No active counters");
        }
        final int cnt = counters.length;
        if (cnt > countMSRs.length) {
            throw new IllegalArgumentException("counters array is too long");
        }

        // Get the counters
        for (int i = 0; i < cnt; i++) {
            counters[i] = countMSRs[i].getValue();
        }
    }

    /**
     * @see org.jnode.vm.x86.performance.X86PerformanceCounters#
     * startCounters(org.jnode.vm.performance.PerformanceCounterEvent[],
     *      org.jnode.vm.x86.VmX86Thread)
     */
    protected void startCounters(PerformanceCounterEvent[] events,
                                 VmX86Thread thread) throws IllegalArgumentException {

        final Map<Integer, P4Event> escrState = new HashMap<Integer, P4Event>();
        final P4Event[] counterState = new P4Event[counters.length];

        final int eventCnt = events.length;
        final MSR[] selectMSRs = new MSR[eventCnt * 2];
        final MSR[] counterMSRs = new MSR[eventCnt];

        int i = 0;
        for (PerformanceCounterEvent e : events) {
            final P4Event evt = (P4Event) e;
            // Find a free ESCR
            final ESCR_RES escr = findFreeESCR(escrState, counterState, evt);
            final CounterMSRInfo cntInfo = counters[indexOf(counterState, evt)];

            // Create the MSRs
            selectMSRs[i * 2 + 0] = new MSR(escr.escr, evt.createESCRValue());
            selectMSRs[i * 2 + 1] = new MSR(cntInfo.cccrMSRIndex, evt.createCCCRValue());
            counterMSRs[i] = new MSR(cntInfo.counterMSRIndex);

            i++;
        }

        thread.setMSRs(counterMSRs, selectMSRs);
    }

    /**
     * Gets the index of the given object in the given array.
     *
     * @param <T>
     * @param arr
     * @param obj
     * @return
     */
    private final <T> int indexOf(T[] arr, T obj) {
        final int max = arr.length;
        for (int i = 0; i < max; i++) {
            if (arr[i] == obj) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Find a free ESCR that can be used for the given event.
     *
     * @param escrState
     * @param evt
     * @return
     */
    private final ESCR_RES findFreeESCR(Map<Integer, P4Event> escrState,
                                        P4Event[] counters, P4Event evt) throws IllegalArgumentException {
        for (ESCR_RES res : evt.escrRestr) {
            final int escrIndex = res.escr;
            if (!escrState.containsKey(escrIndex)) {
                final int cnt;
                if ((cnt = findFreeCounter(counters, res)) >= 0) {
                    escrState.put(escrIndex, evt);
                    counters[cnt] = evt;
                    return res;
                }
            }
        }
        throw new IllegalArgumentException("No free ESCR for event " + evt);
    }

    /**
     * Find a free counter for the given ESCR.
     *
     * @param counters
     * @param escr
     * @return -1 If not found
     */
    private final int findFreeCounter(P4Event[] counters, ESCR_RES escr) {
        for (byte cnt : escr.counters) {
            if (counters[cnt] == null) {
                return cnt;
            }
        }
        return -1;
    }

    /**
     * @see org.jnode.vm.x86.performance.X86PerformanceCounters#stopCounters(org.jnode.vm.x86.VmX86Thread)
     */
    protected void stopCounters(VmX86Thread thread)
        throws IllegalArgumentException {
        final MSR[] selectMSRs = thread.getWriteOnlyMSRs();
        if (selectMSRs != null) {
            final int cnt = selectMSRs.length;
            // Reset the counter selectors
            for (int i = 0; i < cnt; i++) {
                selectMSRs[i].setValue(0);
            }
        }
    }
}
TOP

Related Classes of org.jnode.vm.x86.performance.P4FamilyPerformanceCounters$P4Event

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.