cpuid 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.rdoc +14 -0
  2. data/VERSION +1 -1
  3. data/lib/cpuid.rb +1 -1
  4. data/lib/cpuid/cpuid.rb +139 -21
  5. metadata +1 -1
@@ -2,6 +2,20 @@
2
2
 
3
3
  Access x86 cpuid information from Ruby.
4
4
 
5
+ == Synopsis
6
+
7
+ require 'cpuid'
8
+
9
+ # This should return true, or I don't even know how this gem
10
+ # built on your computer.
11
+ CPUID.has_cpuid?
12
+
13
+ CPUID.vendor_string
14
+ => "GenuineIntel"
15
+
16
+ CPUID.physical_address_size
17
+ => 36
18
+
5
19
  == Note on Patches/Pull Requests
6
20
 
7
21
  * Fork the project.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
@@ -1,3 +1,3 @@
1
-
1
+ $:.unshift File.expand_path(File.dirname(__FILE__))
2
2
  require 'cpuid/cpuid_ext'
3
3
  require 'cpuid/cpuid'
@@ -1,4 +1,7 @@
1
-
1
+ ##
2
+ # = CPUID
3
+ # Module that accesses CPUID information available on x86 processors.
4
+ # Currently mostly supports only Intel meanings behind certain values.
2
5
  module CPUID
3
6
  class UnsupportedFunction < StandardError; end
4
7
  extend self
@@ -7,72 +10,182 @@ module CPUID
7
10
  SIGNATURE_FEATURES_FN = 1
8
11
  SERIAL_NUMBER_FN = 3
9
12
  MAX_EXT_FN = 0x80000000
13
+ EXT_FEATURE_FN = 0x80000001
10
14
  BRAND_STR_FN_1 = 0x80000002
11
15
  BRAND_STR_FN_2 = 0x80000003
12
16
  BRAND_STR_FN_3 = 0x80000004
13
17
  ADDRESS_SIZE_FN = 0x80000008
14
18
 
19
+ INTEL_SYSCALL_CHECK_BIT = 1 << 10
20
+ INTEL_XD_CHECK_BIT = 1 << 19
21
+ INTEL_64_CHECK_BIT = 1 << 28
22
+ INTEL_LAHF_CHECK_BIT = 1
23
+ ##
24
+ # Returns the model information of the processor, which can be used
25
+ # for telling individual processors apart. Note: you will need to use
26
+ # cache information as well to tell some processors apart.
27
+ #
28
+ # @return [Hash] a set of data about the processor. Keys in these results:
29
+ # :family => the family number of the processor
30
+ # :model => the model number of the processor
31
+ # :type => what type of processor it is
32
+ # :step => the stepping of the processor
33
+ # :model_string => a textual meaning behind the "type" value
15
34
  def model_information
16
35
  processor_type = [
17
36
  "Original OEM Processor",
18
37
  "Intel OverDrive",
19
38
  "Dual Processor"
20
39
  ]
21
-
22
- eax, ebx, ecx, edx = run_function(SIGNATURE_FEATURES_FN)
23
-
24
- step = eax & 0xf
25
- model = (eax >> 3) & 0xf
26
- family = (eax >> 8) & 0xf
27
- type = (eax >> 12) & 0x3
28
- ext_model = (eax >> 16) & 0xf
29
- ext_family = (eax >> 20) & 0xff
30
40
 
31
- model = (ext_model << 4) | model
32
- family = (ext_family << 4) | family
33
-
34
- {:family => family, :model => model, :type => type, :step => step, :model_string => processor_type[type]}
41
+ {:family => family, :model => model, :type => type, :step => stepping, :model_string => processor_type[type]}
35
42
  end
36
43
 
44
+ ##
45
+ # The "stepping" of the processor, in number form. Intel term for differentiating processors.
46
+ #
47
+ # @return [Fixnum] the stepping of the processor.
48
+ def stepping; signature & 0xF; end
49
+
50
+ ##
51
+ # The "type" of the processor, in number form. Intel term for differentiating processors.
52
+ # Possible values:
53
+ #
54
+ # 0: Original OEM Processor
55
+ # 1: Intel OverDrive
56
+ # 2: Dual Processor
57
+ #
58
+ # @return [Fixnum] the stepping of the processor.
59
+ def type; (signature >> 12) & 0x3; end
60
+
61
+ ##
62
+ # The full model number of the intel processor.
63
+ #
64
+ # @return [Fixnum] the full model number of the processor.
65
+ def model
66
+ ext_model = ((signature >> 16) & 0xf)
67
+ (ext_model << 4) | ((signature >> 3) & 0xf)
68
+ end
69
+
70
+ ##
71
+ # The full family number of the intel processor.
72
+ #
73
+ # @return [Fixnum] the full family number of the processor.
74
+ def family
75
+ ext_family = (signature >> 20) & 0xff
76
+ (ext_family << 4) | ((signature >> 8) & 0xf)
77
+ end
78
+
79
+ ##
80
+ # Access the serial number of the processor. Will likely fail, because this feature
81
+ # was only enabled for the Pentium III line of intel processors and some very
82
+ # uncommon other manufacturers.
83
+ #
84
+ # TODO: raise UnsupportedFunction if PSN is unavailable instead of retrieving PSN = 0
85
+ #
86
+ # @return [String] the serial number of the processor, in the format
87
+ # "XXXX-XXXX-XXXX-XXXX-XXXX-XXXX"
37
88
  def processor_serial_number
38
89
  eax, ebx, ecx, edx = run_function(SERIAL_NUMBER_FN)
39
90
  [signature, edx, ecx].map {|reg| register_to_hex_s(reg)}.join("-")
40
91
  end
41
92
 
93
+ ##
94
+ # Returns the vendor string, available on all processors.
95
+ # Examples: "GenuineIntel", "AuthenticAMD"
96
+ #
97
+ # @return [String] vendor string for the process.
42
98
  def vendor_string
43
99
  eax, ebx, ecx, edx = run_function(VENDOR_ID_FN)
44
100
  register_to_s(ebx) + register_to_s(edx) + register_to_s(ecx)
45
101
  end
46
-
102
+
103
+ ##
104
+ # Returns the full brand string of the processor
105
+ #
106
+ # @example
107
+ # CPUID.brand_string
108
+ # #=> "Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz\000"
109
+ # @return [String] the brand string of the processor
47
110
  def brand_string
48
111
  [BRAND_STR_FN_1, BRAND_STR_FN_2, BRAND_STR_FN_3].map do |fxn|
49
112
  reg_array_to_s(run_function(fxn))
50
113
  end.join
51
114
  end
52
115
 
116
+ ##
117
+ # Returns the number of maximum bits in this processor's virtual address space
53
118
  def virtual_address_size
54
- run_function(ADDRESS_SIZE_FN) & 0xFF00
119
+ (run_function(ADDRESS_SIZE_FN).first >> 8) & 0xFF
55
120
  end
56
121
 
122
+ ##
123
+ # Returns the number of maximum bits this processor can address in physical memory
57
124
  def physical_address_size
58
- run_function(ADDRESS_SIZE_FN) & 0x00FF
125
+ run_function(ADDRESS_SIZE_FN).first & 0xFF
126
+ end
127
+
128
+ ##
129
+ # Returns whether the process supports the SYSCALL and SYSRET instructions.
130
+ #
131
+ # @return [Boolean]
132
+ def has_syscall?
133
+ !!(run_function(EXT_FEATURE_FN)[3] & INTEL_SYSCALL_CHECK_BIT)
134
+ end
135
+
136
+ ##
137
+ # Returns whether the process supports the SYSCALL and SYSRET instructions.
138
+ #
139
+ # @return [Boolean]
140
+ def has_xd_bit?
141
+ !!(run_function(EXT_FEATURE_FN)[3] & INTEL_XD_CHECK_BIT)
142
+ end
143
+
144
+ ##
145
+ # Returns whether the process supports the LAHF and SAHF instructions.
146
+ #
147
+ # @return [Boolean]
148
+ def has_lahf?
149
+ !!(run_function(EXT_FEATURE_FN)[2] & INTEL_LAHF_CHECK_BIT)
150
+ end
151
+
152
+ ##
153
+ # Returns whether the processor supports the x86_64 instruction set.
154
+ #
155
+ # @return [Boolean] does the processor support x86_64?
156
+ def has_x64?
157
+ !!(run_function(EXT_FEATURE_FN)[3] & INTEL_64_CHECK_BIT)
59
158
  end
60
159
 
61
160
  #private
62
161
 
63
162
  def signature
64
- run_function(SIGNATURE_FEATURES_FN).first
163
+ @signature ||= run_function(SIGNATURE_FEATURES_FN).first
65
164
  end
66
165
 
166
+ ##
167
+ # Only runs the given CPUID function if the processor supports it, by checking the
168
+ # processor's maximum parameter values
169
+ #
170
+ # @raise UnsupportedFunction raised if the requested function is not supported by
171
+ # the processor
172
+ # @param [Fixnum] fn the function to check and run
173
+ # @return [Array<Fixnum>] an array of 4 values: eax, ebx, ecx, edx, returned by the processor.
67
174
  def run_function(fn)
68
- if can_run(fn)
175
+ if can_run?(fn)
69
176
  run_cpuid(fn)
70
177
  else
71
178
  raise UnsupportedFunction.new("The requested CPUID function 0x#{fn.to_s(16).rjust(8,"0")} is unsupported by your CPU.")
72
179
  end
73
180
  end
74
181
 
75
- def can_run(fn)
182
+ ##
183
+ # Checks if the processor supports the given function, by using the
184
+ # processor's maximum parameter functions (also a part of the CPUID information)
185
+ #
186
+ # @param [Fixnum] fn the function to check for availability
187
+ # @return [Boolean] does the processor support the function?
188
+ def can_run?(fn)
76
189
  (fn < MAX_EXT_FN && fn <= max_basic_param) || (fn >= MAX_EXT_FN && fn <= max_extended_param)
77
190
  end
78
191
 
@@ -87,7 +200,12 @@ module CPUID
87
200
  def get_byte(reg, i)
88
201
  (reg >> (i * 8)) & 0xFF
89
202
  end
90
-
203
+
204
+ ##
205
+ # Converts 4 bytes to 4 characters, reversing the order due to little-endian.
206
+ #
207
+ # @param [Fixnum] reg the register value to convert to a string
208
+ # @return [String] a 4-character string converted from the register
91
209
  def register_to_s(reg)
92
210
  str = ""
93
211
  0.upto(3) do |idx|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpuid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Edgar