From: <ep...@us...> - 2013-11-12 15:20:02
|
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. |