Revision: 5995 http://sourceforge.net/p/jnode/svn/5995 Author: epr Date: 2013-11-12 15:19:59 +0000 (Tue, 12 Nov 2013) Log Message: ----------- Improved CPUID.
Modified Paths: -------------- trunk/core/src/core/org/jnode/vm/Unsafe.java trunk/core/src/core/org/jnode/vm/scheduler/VmProcessor.java trunk/core/src/core/org/jnode/vm/x86/UnsafeX86.java trunk/core/src/core/org/jnode/vm/x86/VmX86Processor.java trunk/core/src/core/org/jnode/vm/x86/X86CpuID.java trunk/core/src/native/x86/jnode.asm trunk/core/src/test/org/jnode/test/IRTest.java Added Paths: ----------- trunk/core/src/native/x86/unsafex86-cpuid.asm Removed Paths: ------------- trunk/core/src/native/x86/unsafe-cpuid.asm Modified: trunk/core/src/core/org/jnode/vm/Unsafe.java =================================================================== --- trunk/core/src/core/org/jnode/vm/Unsafe.java 2013-11-12 08:49:28 UTC (rev 5994) +++ trunk/core/src/core/org/jnode/vm/Unsafe.java 2013-11-12 15:19:59 UTC (rev 5995) @@ -699,19 +699,6 @@ } /** - * Read CPU identification data. - * <p/> - * If id is null, this method will return the length of the id array that is - * required to fit all data. If id is not null and long enough, it is filled - * with all identification data. - * - * @param id - * @return The required length of id. - */ - @Internal - public static native int getCPUID(int[] id); - - /** * List the current stacktrace on the kernel debug output. * * @throws UninterruptiblePragma Modified: trunk/core/src/core/org/jnode/vm/scheduler/VmProcessor.java =================================================================== --- trunk/core/src/core/org/jnode/vm/scheduler/VmProcessor.java 2013-11-12 08:49:28 UTC (rev 5994) +++ trunk/core/src/core/org/jnode/vm/scheduler/VmProcessor.java 2013-11-12 15:19:59 UTC (rev 5995) @@ -43,6 +43,7 @@ import org.jnode.vm.facade.VmUtils; import org.jnode.vm.objects.VmSystemObject; import org.jnode.vm.performance.PerformanceCounters; +import org.jnode.vm.x86.UnsafeX86; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.ObjectReference; import org.vmmagic.unboxed.Word; @@ -574,10 +575,7 @@ */ public final CpuID getCPUID() { if (cpuId == null) { - final int length = Unsafe.getCPUID(null); - final int[] id = new int[length]; - Unsafe.getCPUID(id); - cpuId = loadCPUID(id); + cpuId = loadCPUID(); } return cpuId; } @@ -588,7 +586,7 @@ * @param id The identification returned by Unsafe.getCpuID * @return CpuID */ - protected abstract CpuID loadCPUID(int[] id); + protected abstract CpuID loadCPUID(); /** * Set the CPU id. Modified: trunk/core/src/core/org/jnode/vm/x86/UnsafeX86.java =================================================================== --- trunk/core/src/core/org/jnode/vm/x86/UnsafeX86.java 2013-11-12 08:49:28 UTC (rev 5994) +++ trunk/core/src/core/org/jnode/vm/x86/UnsafeX86.java 2013-11-12 15:19:59 UTC (rev 5995) @@ -20,7 +20,9 @@ package org.jnode.vm.x86; +import org.jnode.annotation.Internal; import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Word; /** @@ -69,6 +71,16 @@ static final native Address getCR3(); /** + * Read CPU identification data. + * <p/> + * @param input The number to put in EAX + * @param result An array of length 4 (or longer) where eax, ebx, ecx, edx is stored into. + * @return 1 on success, 0 otherwise (result == null or result.length less than 4). + */ + @Internal + public static native int getCPUID(Word input, int[] result); + + /** * Gets the address of first entry in the multiboot mmap table. * * @return Modified: trunk/core/src/core/org/jnode/vm/x86/VmX86Processor.java =================================================================== --- trunk/core/src/core/org/jnode/vm/x86/VmX86Processor.java 2013-11-12 08:49:28 UTC (rev 5994) +++ trunk/core/src/core/org/jnode/vm/x86/VmX86Processor.java 2013-11-12 15:19:59 UTC (rev 5995) @@ -174,8 +174,8 @@ * * @return CpuID */ - protected CpuID loadCPUID(int[] id) { - return new X86CpuID(id); + protected CpuID loadCPUID() { + return X86CpuID.loadFromCurrentCpu(); } /** Modified: trunk/core/src/core/org/jnode/vm/x86/X86CpuID.java =================================================================== --- trunk/core/src/core/org/jnode/vm/x86/X86CpuID.java 2013-11-12 08:49:28 UTC (rev 5994) +++ trunk/core/src/core/org/jnode/vm/x86/X86CpuID.java 2013-11-12 15:19:59 UTC (rev 5995) @@ -22,6 +22,8 @@ import org.jnode.util.NumberUtils; import org.jnode.vm.CpuID; +import org.jnode.vm.Unsafe; +import org.vmmagic.unboxed.Word; /** * Class used to identify the current processor. @@ -60,9 +62,18 @@ public static final int FEAT_TM = (1 << 29); public static final int FEAT_PBE = (1 << 31); // Extended features - public static final long FEAT_EST = (1L << 39); - public static final long FEAT_TM2 = (1L << 40); - public static final long FEAT_CNXTID = (1L << 42); + 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; @@ -83,6 +94,8 @@ 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. @@ -123,14 +136,15 @@ id[1] = 0x756e6547; id[2] = 0x6c65746e; id[3] = 0x49656e69; - return new X86CpuID(id); + return new X86CpuID(id, "?"); } /** * Initialize this instance */ - X86CpuID(int[] data) { + 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; @@ -138,10 +152,79 @@ 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); + + // Load hypervisor data + if (id.hasHYPERVISOR()) { + UnsafeX86.getCPUID(Word.fromIntZeroExtend(0x40000001), regs); + if (regs[0] == 0x31237648) { + // 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 + id.hypervisorVendor = buf.toString().trim(); + } + } + + return id; + } + /** + * Processor vendor string + */ public String getName() { return getVendor(); } + + /** + * Processor brand string + */ + public String getBrand() { + return brand; + } /** * Gets the processor name. @@ -177,7 +260,7 @@ return getVendor().equals(X86Vendor.AMD.getId()); } - private final void intToString(StringBuilder buf, int value) { + 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)); @@ -404,6 +487,10 @@ public final boolean hasCNXTID() { return hasFeature(FEAT_CNXTID); } + + public final boolean hasHYPERVISOR() { + return hasFeature(FEAT_HYPERVISOR); + } /** * Convert all features to a human readable string. @@ -442,9 +529,18 @@ 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(); } @@ -473,23 +569,47 @@ */ public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append("CPU:"); - sb.append(" name:"); + sb.append("CPUID"); + sb.append('\n'); + + sb.append(" name : "); sb.append(getName()); - sb.append(" family:"); + sb.append('\n'); + + sb.append(" brand : "); + sb.append(getBrand()); + sb.append('\n'); + + sb.append(" family : "); sb.append(getFamily()); - sb.append(" model:"); + sb.append('\n'); + + sb.append(" model : "); sb.append(getModel()); - sb.append(" step:"); + 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(" #log.proc: "); + sb.append(getLogicalProcessors()); + sb.append('\n'); } - sb.append(" features:"); + if (hypervisorVendor != null) { + sb.append(" hyperv. : "); + sb.append(hypervisorVendor); + sb.append('\n'); + } + sb.append(" features : "); sb.append(getFeatureString()); - sb.append(" raw:"); + sb.append('\n'); + + sb.append(" raw : "); sb.append(NumberUtils.hex(data, 8)); + sb.append('\n'); + return sb.toString(); } } Modified: trunk/core/src/native/x86/jnode.asm =================================================================== --- trunk/core/src/native/x86/jnode.asm 2013-11-12 08:49:28 UTC (rev 5994) +++ trunk/core/src/native/x86/jnode.asm 2013-11-12 15:19:59 UTC (rev 5995) @@ -133,7 +133,7 @@ %include "unsafe.asm" %include "unsafe-binop.asm" %include "unsafe-setmulti.asm" -%include "unsafe-cpuid.asm" +%include "unsafex86-cpuid.asm" %include "unsafex86.asm" %include "unsafex86-mm.asm" %include "vm.asm" Deleted: trunk/core/src/native/x86/unsafe-cpuid.asm =================================================================== --- trunk/core/src/native/x86/unsafe-cpuid.asm 2013-11-12 08:49:28 UTC (rev 5994) +++ trunk/core/src/native/x86/unsafe-cpuid.asm 2013-11-12 15:19:59 UTC (rev 5995) @@ -1,66 +0,0 @@ -; ----------------------------------------------- -; $Id$ -; -; Native method implementation for org.jnode.vm.Unsafe -; of the CPU identification methods. -; -; Author : E. Prangsma -; ----------------------------------------------- - -; * Read CPU identification data. -; * -; * If id is null, this method will return the length of the id array -; * that is required to fit all data. -; * If id is not null and long enough, it is filled with all identification -; * data. -; * -; * @param id -; * @return The required length of id. -; public static native int getCPUID(int[] id); -GLABEL Q43org5jnode2vm6Unsafe23getCPUID2e285bI29I - mov AAX,[ASP+SLOT_SIZE] ; Get id - push ADI - push ABX - push ACX - push ADX - - mov ADI,AAX ; edi = id - xor eax,eax - cpuid ; eax contains maximum input value - lea ecx,[eax+1] ; Store maximum+1 for later - lea eax,[eax*4+4] ; Calculate id.length (4 registers * (maximum input value+1)) - - test ADI,ADI ; is id null? - je cpuid_ret - cmp eax,[ADI+VmArray_LENGTH_OFFSET*SLOT_SIZE] - ja cpuid_ret ; id is not large enough? - - lea ADI,[ADI+VmArray_DATA_OFFSET*SLOT_SIZE] ; Load &id[0] into edi - push AAX - pushf - cld - xor eax,eax -cpuid_loop: - push AAX - push ACX - cpuid - stosd ; store eax - mov eax,ebx - stosd ; store ebx - mov eax,ecx - stosd ; store ecx - mov eax,edx - stosd ; store edx - pop ACX - pop AAX - inc eax - loop cpuid_loop - popf - pop AAX - -cpuid_ret: - pop ADX - pop ACX - pop ABX - pop ADI - ret SLOT_SIZE Added: trunk/core/src/native/x86/unsafex86-cpuid.asm =================================================================== --- trunk/core/src/native/x86/unsafex86-cpuid.asm (rev 0) +++ trunk/core/src/native/x86/unsafex86-cpuid.asm 2013-11-12 15:19:59 UTC (rev 5995) @@ -0,0 +1,51 @@ +; ----------------------------------------------- +; $Id: unsafe-cpuid.asm 1036 2005-01-30 10:41:32Z epr $ +; +; Native method implementation for org.jnode.vm.x86.UnsafeX86 +; of the CPU identification methods. +; +; Author : E. Prangsma +; ----------------------------------------------- + +; * Read CPU identification data. +; * +; * @param input The number to put in EAX +; * @param result An array of length 4 (or longer) where eax, ebx, ecx, edx is stored into. +; * @return 1 on success, 0 otherwise (result == null or result.length less than 4). +; public static native int getCPUID(Word input, int[] result); +GLABEL Q53org5jnode2vm3x869UnsafeX8623getCPUID2e28Lorg2fvmmagic2funboxed2fWord3b5bI29I + push ADI + mov ADI,[ASP+(2*SLOT_SIZE)] ; Get result + mov AAX,[ASP+(3*SLOT_SIZE)] ; Get input + push ABX + push ACX + push ADX + + test ADI,ADI ; is id null? + je cpuid_invalid_arg + mov ebx,4 ; We need an array of length 4 (or more) + cmp ebx,[ADI+VmArray_LENGTH_OFFSET*SLOT_SIZE] + ja cpuid_invalid_arg; id is not large enough? + + lea ADI,[ADI+VmArray_DATA_OFFSET*SLOT_SIZE] ; Load &id[0] into edi + ; Execute CPUID + cpuid + mov [ADI+0],eax ; store eax + mov [ADI+4],ebx ; store ebx + mov [ADI+8],ecx ; store ecx + mov [ADI+12],edx ; store edx + ; Signal valid return + mov eax,1 ; Return 1 + jmp cpuid_ret + +cpuid_invalid_arg: + xor eax,eax ; Return 0 + +cpuid_ret: + pop ADX + pop ACX + pop ABX + pop ADI + ret SLOT_SIZE + + \ No newline at end of file Modified: trunk/core/src/test/org/jnode/test/IRTest.java =================================================================== --- trunk/core/src/test/org/jnode/test/IRTest.java 2013-11-12 08:49:28 UTC (rev 5994) +++ trunk/core/src/test/org/jnode/test/IRTest.java 2013-11-12 15:19:59 UTC (rev 5995) @@ -161,7 +161,7 @@ cfg.deconstrucSSA(); cfg.fixupAddresses(); - final Map<Variable, Variable<T>> liveVariables = new BootableHashMap<Variable, Variable<T>>(); + final Map<Variable<?>, Variable<T>> liveVariables = new BootableHashMap<Variable<?>, Variable<T>>(); for (IRBasicBlock<T> b : cfg) { System.out.println(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ November Webinars for C, C++, Fortran Developers Accelerate application performance with scalable programming models. Explore techniques for threading, error checking, porting, and tuning. Get the most from the latest Intel processors and coprocessors. See abstracts and register http://pubads.g.doubleclick.net/gampad/clk?id=60136231&iu=/4140/ostg.clktrk _______________________________________________ Jnode-svn-commits mailing list Jnode-svn-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jnode-svn-commits