|
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.
|