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

Reply via email to