Package org.jnode.vm.x86

Source Code of org.jnode.vm.x86.X86CpuID

/*
* $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;

import org.jnode.util.NumberUtils;
import org.jnode.vm.CpuID;
import org.vmmagic.unboxed.Word;

/**
* Class used to identify the current processor.
*
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class X86CpuID extends CpuID {

    public static final int FEAT_FPU = (1 << 0);
    public static final int FEAT_VME = (1 << 1);
    public static final int FEAT_DE = (1 << 2);
    public static final int FEAT_PSE = (1 << 3);
    public static final int FEAT_TSC = (1 << 4);
    public static final int FEAT_MSR = (1 << 5);
    public static final int FEAT_PAE = (1 << 6);
    public static final int FEAT_MCE = (1 << 7);
    public static final int FEAT_CX8 = (1 << 8);
    public static final int FEAT_APIC = (1 << 9);
    public static final int FEAT_SEP = (1 << 11);
    public static final int FEAT_MTRR = (1 << 12);
    public static final int FEAT_PGE = (1 << 13);
    public static final int FEAT_MCA = (1 << 14);
    public static final int FEAT_CMOV = (1 << 15);
    public static final int FEAT_PAT = (1 << 16);
    public static final int FEAT_PSE36 = (1 << 17);
    public static final int FEAT_PSN = (1 << 18);
    public static final int FEAT_CLFSH = (1 << 19);
    public static final int FEAT_DS = (1 << 21);
    public static final int FEAT_ACPI = (1 << 22);
    public static final int FEAT_MMX = (1 << 23);
    public static final int FEAT_FXSR = (1 << 24);
    public static final int FEAT_SSE = (1 << 25);
    public static final int FEAT_SSE2 = (1 << 26);
    public static final int FEAT_SS = (1 << 27);
    public static final int FEAT_HTT = (1 << 28);
    public static final int FEAT_TM = (1 << 29);
    public static final int FEAT_PBE = (1 << 31);
    // Extended features
    public static final long FEAT_PNI = (1L << 32); // Prescott New Instructions (SSE3)
    public static final long FEAT_PCLMULQDQ = (1L << 33); // PCLMULQDQ support
    public static final long FEAT_DTES64 = (1L << 34); // 64-bit debug store (edx bit 21)
    public static final long FEAT_MONITOR = (1L << 35); // MONITOR and MWAIT instructions (SSE3)
    public static final long FEAT_DS_CPL = (1L << 36); // CPL qualified debug store
    public static final long FEAT_VMX = (1L << 37); // Virtual Machine eXtensions
    public static final long FEAT_SMX = (1L << 38); // Safer Mode Extensions (LaGrande)
    public static final long FEAT_EST = (1L << 39); // Enhanced SpeedStep
    public static final long FEAT_TM2 = (1L << 40); // Thermal Monitor 2
    public static final long FEAT_SSSE3 = (1L << 41); // Supplemental SSE3 instructions
    public static final long FEAT_CNXTID = (1L << 42); // Context ID
    public static final long FEAT_HYPERVISOR = (1L << 63);
        // Running on a hypervisor (always 0 on a real CPU, but also with some hypervisors)

    // Family codes
    public static final int FAM_486 = 0x04;
    public static final int FAM_PENTIUM = 0x05;
    public static final int FAM_PENTIUM_2_3 = 0x06;
    public static final int FAM_PENTIUM4 = 0x0F;

    /**
     * The cpu id data
     */
    private final int[] data;
    /**
     * Vendor of the processor
     */
    private String vendor;
    private final int steppingID;
    private final int model;
    private final int family;
    private final int features;
    private final long exFeatures;
    private final String brand;
    private String hypervisorVendor;

    /**
     * Create a cpu id that contains the data of a processor identified by the given processor id.
     *
     * @param procId "i586", "pentium" for Pentium, "i686", "pentium2" for Pentium II, "pentium3" for
     *               Pentium III "pentium4" for Pentium 4 can be null
     * @return New cpu id.
     */
    public static X86CpuID createID(String procId) {
        // Handle default
        if (procId == null) {
            procId = "pentium";
        }
        final int[] id;
        if (procId.equals("pentium4")) {
            // Pentium 4
            id = new int[12];
            id[0] = 0x02;
            id[7] = FEAT_FPU | FEAT_PSE | FEAT_CMOV | FEAT_SSE | FEAT_SSE2;
        } else if (procId.equals("pentium3")) {
            // Pentium 3
            id = new int[16];
            id[0] = 0x03;
            id[7] = FEAT_FPU | FEAT_PSE | FEAT_CMOV | FEAT_SSE;
        } else if (procId.equals("pentium2")) {
            // Pentium 2
            id = new int[12];
            id[0] = 0x02;
            id[7] = FEAT_FPU | FEAT_PSE | FEAT_CMOV;

        } else {
            // Pentium
            id = new int[8];
            id[0] = 0x01;
            id[7] = FEAT_FPU | FEAT_PSE;
        }
        // Set name GenuineIntel
        id[1] = 0x756e6547;
        id[2] = 0x6c65746e;
        id[3] = 0x49656e69;
        return new X86CpuID(id, "?");
    }

    /**
     * Initialize this instance
     */
    X86CpuID(int[] data, String brand) {
        this.data = data;
        this.brand = brand;
        final int eax = data[4];
        this.steppingID = eax & 0xF;
        this.model = (eax >> 4) & 0xF;
        this.family = (eax >> 8) & 0xF;
        this.features = data[7];
        this.exFeatures = features | (((long) data[6]) << 32);
    }

    /**
     * Load a new CpuID from the current CPU.
     *
     * @return
     */
    static X86CpuID loadFromCurrentCpu() {

        // Load low values (eax=0)
        int[] regs = new int[4];
        UnsafeX86.getCPUID(Word.zero(), regs);

        final int count = regs[0] + 1;
        int[] data = new int[count * 4];

        int index = 0;
        for (int i = 0; i < count; i++) {
            UnsafeX86.getCPUID(Word.fromIntZeroExtend(i), regs);
            data[index++] = regs[0];
            data[index++] = regs[1];
            data[index++] = regs[2];
            data[index++] = regs[3];
        }

        // Load extended functions (0x80000000)
        String brand = "?";
        final Word extendedBase = Word.fromIntZeroExtend(0x80000000);
        UnsafeX86.getCPUID(extendedBase, regs);
        Word max = Word.fromIntZeroExtend(regs[0]);
        if (max.GE(extendedBase.add(4))) {
            // Load brand 0x80000002..0x80000004
            final StringBuilder buf = new StringBuilder();
            for (int i = 0; i < 3; i++) {
                UnsafeX86.getCPUID(extendedBase.add(2 + i), regs);
                intToString(buf, regs[0]);
                intToString(buf, regs[1]);
                intToString(buf, regs[2]);
                intToString(buf, regs[3]);
            }
            brand = buf.toString().trim();
        }

        X86CpuID id = new X86CpuID(data, brand);
        id.detectHyperV();
        return id;
    }

    /**
     * Try to detect if we're running in HyperV.
     *
     * @return true if we're running in HyperV, false otherwise.
     */
    public boolean detectHyperV() {
        if (!hasHYPERVISOR())
            return false;

        int[] regs = new int[4];
        UnsafeX86.getCPUID(Word.fromIntZeroExtend(0x40000001), regs);
        if (regs[0] != 0x31237648)
            return false;
        // Found 'Hv#1' Hypervisor vendor neutral identification
        UnsafeX86.getCPUID(Word.fromIntZeroExtend(0x40000000), regs);
        final StringBuilder buf = new StringBuilder();
        intToString(buf, regs[1]); // ebx
        intToString(buf, regs[2]); // ecx
        intToString(buf, regs[3]); // edx
        hypervisorVendor = buf.toString().trim();
        return true;
    }

    /**
     * Processor vendor string
     */
    public String getName() {
        return getVendor();
    }

    /**
     * Processor brand string
     */
    public String getBrand() {
        return brand;
    }

    /**
     * Gets the processor name.
     *
     * @return The processor name
     */
    public String getVendor() {
        if (vendor == null) {
            final StringBuilder buf = new StringBuilder();
            intToString(buf, data[1]);
            intToString(buf, data[3]);
            intToString(buf, data[2]);
            vendor = buf.toString();
        }
        return vendor;
    }

    /**
     * Is this the id of an Intel CPU.
     *
     * @return {@code true} for an Intel CPU, otherwise {@code false}
     */
    public boolean isIntel() {
        return getVendor().equals(X86Vendor.INTEL.getId());
    }

    /**
     * Is this the id of an AMD CPU.
     *
     * @return {@code true} for an AMD CPU, otherwise {@code false}
     */
    public boolean isAMD() {
        return getVendor().equals(X86Vendor.AMD.getId());
    }

    private static final void intToString(StringBuilder buf, int value) {
        buf.append((char) (value & 0xFF));
        buf.append((char) ((value >> 8) & 0xFF));
        buf.append((char) ((value >> 16) & 0xFF));
        buf.append((char) ((value >>> 24) & 0xFF));
    }

    /**
     * @return Returns the family.
     */
    public final int getFamily() {
        return this.family;
    }

    /**
     * @return Returns the model.
     */
    public final int getModel() {
        return this.model;
    }

    /**
     * @return Returns the steppingID.
     */
    public final int getSteppingID() {
        return this.steppingID;
    }

    /**
     * @return Returns the features.
     */
    public final int getFeatures() {
        return this.features;
    }

    /**
     * Has this CPU a given feature.
     *
     * @param feature
     * @return boolean
     */
    public final boolean hasFeature(long feature) {
        return ((this.exFeatures & feature) == feature);
    }

    /**
     * Gets the number of logical processors.
     * This method will only return more then 1 of this processor
     * has the Hyper Threading feature.
     *
     * @return The number of logical processors.
     */
    public final int getLogicalProcessors() {
        if (hasFeature(FEAT_HTT)) {
            // EBX bits 16-23 when EAX == 1
            return (data[5] >> 16) & 0xFF;
        } else {
            return 1;
        }
    }

    /**
     * Calculate the physical package id for the given APIC id.
     *
     * @param apicId
     * @return the physical package id.
     */
    public final int getPhysicalPackageId(int apicId) {
        int index_lsb = 0;
        int index_msb = 31;
        final int numLogicalProcessors = getLogicalProcessors();

        int tmp = numLogicalProcessors;
        while ((tmp & 1) == 0) {
            tmp >>= 1;
            index_lsb++;
        }
        tmp = numLogicalProcessors;
        while ((tmp & 0x80000000) == 0) {
            tmp <<= 1;
            index_msb--;
        }
        if (index_lsb != index_msb) {
            index_msb++;
        }

        return ((data[5] >> 24) & 0xFF) >> index_msb;
    }

    /**
     * Has this CPU a given feature.
     *
     * @param feature
     * @return boolean
     */
    public final boolean hasFeature(int feature) {
        return ((this.features & feature) == feature);
    }

    public final boolean hasFPU() {
        return hasFeature(FEAT_FPU);
    }

    public final boolean hasVME() {
        return hasFeature(FEAT_VME);
    }

    public final boolean hasDE() {
        return hasFeature(FEAT_DE);
    }

    public final boolean hasPSE() {
        return hasFeature(FEAT_PSE);
    }

    public final boolean hasTSC() {
        return hasFeature(FEAT_TSC);
    }

    public final boolean hasMSR() {
        return hasFeature(FEAT_MSR);
    }

    public final boolean hasPAE() {
        return hasFeature(FEAT_PAE);
    }

    public final boolean hasMCE() {
        return hasFeature(FEAT_MCE);
    }

    public final boolean hasCX8() {
        return hasFeature(FEAT_CX8);
    }

    public final boolean hasAPIC() {
        return hasFeature(FEAT_APIC);
    }

    public final boolean hasSEP() {
        return hasFeature(FEAT_SEP);
    }

    public final boolean hasMTRR() {
        return hasFeature(FEAT_MTRR);
    }

    public final boolean hasPGE() {
        return hasFeature(FEAT_PGE);
    }

    public final boolean hasMCA() {
        return hasFeature(FEAT_MCA);
    }

    public final boolean hasCMOV() {
        return hasFeature(FEAT_CMOV);
    }

    public final boolean hasPAT() {
        return hasFeature(FEAT_PAT);
    }

    public final boolean hasPSE36() {
        return hasFeature(FEAT_PSE36);
    }

    public final boolean hasPSN() {
        return hasFeature(FEAT_PSN);
    }

    public final boolean hasCLFSH() {
        return hasFeature(FEAT_CLFSH);
    }

    public final boolean hasDS() {
        return hasFeature(FEAT_DS);
    }

    public final boolean hasACPI() {
        return hasFeature(FEAT_ACPI);
    }

    public final boolean hasMMX() {
        return hasFeature(FEAT_MMX);
    }

    public final boolean hasFXSR() {
        return hasFeature(FEAT_FXSR);
    }

    public final boolean hasSSE() {
        return hasFeature(FEAT_SSE);
    }

    public final boolean hasSSE2() {
        return hasFeature(FEAT_SSE2);
    }

    public final boolean hasSS() {
        return hasFeature(FEAT_SS);
    }

    public final boolean hasHTT() {
        return hasFeature(FEAT_HTT);
    }

    public final boolean hasTM() {
        return hasFeature(FEAT_TM);
    }

    public final boolean hasPBE() {
        return hasFeature(FEAT_PBE);
    }

    // Extended features
    public final boolean hasEST() {
        return hasFeature(FEAT_EST);
    }

    public final boolean hasTM2() {
        return hasFeature(FEAT_TM2);
    }

    public final boolean hasCNXTID() {
        return hasFeature(FEAT_CNXTID);
    }

    public final boolean hasHYPERVISOR() {
        return hasFeature(FEAT_HYPERVISOR);
    }

    /**
     * Convert all features to a human readable string.
     *
     * @return The available features.
     */
    private final String getFeatureString() {
        final StringBuilder buf = new StringBuilder();
        getFeatureString(buf, FEAT_FPU, "FPU");
        getFeatureString(buf, FEAT_VME, "VME");
        getFeatureString(buf, FEAT_DE, "DE");
        getFeatureString(buf, FEAT_PSE, "PSE");
        getFeatureString(buf, FEAT_TSC, "TSC");
        getFeatureString(buf, FEAT_MSR, "MSR");
        getFeatureString(buf, FEAT_PAE, "PAE");
        getFeatureString(buf, FEAT_MCE, "MCE");
        getFeatureString(buf, FEAT_CX8, "CX8");
        getFeatureString(buf, FEAT_APIC, "APIC");
        getFeatureString(buf, FEAT_SEP, "SEP");
        getFeatureString(buf, FEAT_MTRR, "MTRR");
        getFeatureString(buf, FEAT_PGE, "PGE");
        getFeatureString(buf, FEAT_MCA, "MCA");
        getFeatureString(buf, FEAT_CMOV, "CMOV");
        getFeatureString(buf, FEAT_PAT, "PAT");
        getFeatureString(buf, FEAT_PSE36, "PSE36");
        getFeatureString(buf, FEAT_PSN, "PSN");
        getFeatureString(buf, FEAT_CLFSH, "CLFSH");
        getFeatureString(buf, FEAT_DS, "DS");
        getFeatureString(buf, FEAT_ACPI, "ACPI");
        getFeatureString(buf, FEAT_MMX, "MMX");
        getFeatureString(buf, FEAT_FXSR, "FXSR");
        getFeatureString(buf, FEAT_SSE, "SSE");
        getFeatureString(buf, FEAT_SSE2, "SSE2");
        getFeatureString(buf, FEAT_SS, "SS");
        getFeatureString(buf, FEAT_HTT, "HTT");
        getFeatureString(buf, FEAT_TM, "TM");
        getFeatureString(buf, FEAT_PBE, "PBE");
        // Extended features
        getFeatureString(buf, FEAT_PNI, "PNI");
        getFeatureString(buf, FEAT_PCLMULQDQ, "PCLMULQDQ");
        getFeatureString(buf, FEAT_DTES64, "DTES64");
        getFeatureString(buf, FEAT_MONITOR, "MONITOR");
        getFeatureString(buf, FEAT_DS_CPL, "DS_CPL");
        getFeatureString(buf, FEAT_VMX, "VMX");
        getFeatureString(buf, FEAT_SMX, "SMX");
        getFeatureString(buf, FEAT_EST, "EST");
        getFeatureString(buf, FEAT_TM2, "TM2");
        getFeatureString(buf, FEAT_SSSE3, "SSSE3");
        getFeatureString(buf, FEAT_CNXTID, "CNXTID");
        getFeatureString(buf, FEAT_HYPERVISOR, "HYPERVISOR");
        return buf.toString();
    }

    private final void getFeatureString(StringBuilder buf, int feature, String featName) {
        if (hasFeature(feature)) {
            if (buf.length() > 0) {
                buf.append(',');
            }
            buf.append(featName);
        }
    }

    private final void getFeatureString(StringBuilder buf, long feature, String featName) {
        if (hasFeature(feature)) {
            if (buf.length() > 0) {
                buf.append(',');
            }
            buf.append(featName);
        }
    }

    /**
     * Convert to a string representation.
     *
     * @see java.lang.Object#toString()
     */
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("CPUID");
        sb.append('\n');

        sb.append(" name     : ");
        sb.append(getName());
        sb.append('\n');

        sb.append(" brand    : ");
        sb.append(getBrand());
        sb.append('\n');

        sb.append(" family   : ");
        sb.append(getFamily());
        sb.append('\n');

        sb.append(" model    : ");
        sb.append(getModel());
        sb.append('\n');

        sb.append(" step     : ");
        sb.append(getSteppingID());
        sb.append('\n');

        if (hasFeature(FEAT_HTT)) {
            sb.append(" #log.proc: ");
            sb.append(getLogicalProcessors());
            sb.append('\n');
        }
        if (hypervisorVendor != null) {
            sb.append(" hyperv.  : ");
            sb.append(hypervisorVendor);
            sb.append('\n');
        }
        sb.append(" features : ");
        sb.append(getFeatureString());
        sb.append('\n');

        sb.append(" raw      : ");
        sb.append(NumberUtils.hex(data, 8));
        sb.append('\n');

        return sb.toString();
    }
}
TOP

Related Classes of org.jnode.vm.x86.X86CpuID

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.