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.
- data/README.rdoc +14 -0
- data/VERSION +1 -1
- data/lib/cpuid.rb +1 -1
- data/lib/cpuid/cpuid.rb +139 -21
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -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.
|
1
|
+
0.2.1
|
data/lib/cpuid.rb
CHANGED
data/lib/cpuid/cpuid.rb
CHANGED
@@ -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
|
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) &
|
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) &
|
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
|
-
|
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|
|