cpuid 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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