cpuid 0.3.0 → 0.4.0
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/VERSION +1 -1
- data/lib/cpuid.rb +3 -1
- data/lib/cpuid/cpuid.rb +9 -182
- data/lib/cpuid/features.rb +45 -0
- data/lib/cpuid/processor.rb +152 -0
- metadata +3 -1
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/lib/cpuid.rb
CHANGED
data/lib/cpuid/cpuid.rb
CHANGED
@@ -1,193 +1,20 @@
|
|
1
|
+
require 'cpuid/features'
|
2
|
+
require 'cpuid/processor'
|
3
|
+
|
1
4
|
##
|
2
5
|
# = CPUID
|
3
6
|
# Module that accesses CPUID information available on x86 processors.
|
4
7
|
# Currently mostly supports only Intel meanings behind certain values.
|
5
8
|
module CPUID
|
6
9
|
class UnsupportedFunction < StandardError; end
|
7
|
-
|
10
|
+
include Features
|
11
|
+
include Processor
|
8
12
|
|
9
|
-
|
10
|
-
SIGNATURE_FEATURES_FN = 1
|
11
|
-
SERIAL_NUMBER_FN = 3
|
12
|
-
MAX_EXT_FN = 0x80000000
|
13
|
-
EXT_FEATURE_FN = 0x80000001
|
14
|
-
BRAND_STR_FN_1 = 0x80000002
|
15
|
-
BRAND_STR_FN_2 = 0x80000003
|
16
|
-
BRAND_STR_FN_3 = 0x80000004
|
17
|
-
EXT_L2_FN = 0x80000006
|
18
|
-
POWER_MANAGEMENT_FN = 0x80000007
|
19
|
-
ADDRESS_SIZE_FN = 0x80000008
|
13
|
+
extend self
|
20
14
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
INTEL_LAHF_CHECK_BIT = 1
|
25
|
-
INTEL_TSC_INVARIANCE_CHECK_BIT = 1 << 7
|
26
|
-
##
|
27
|
-
# Returns the model information of the processor, which can be used
|
28
|
-
# for telling individual processors apart. Note: you will need to use
|
29
|
-
# cache information as well to tell some processors apart.
|
30
|
-
#
|
31
|
-
# @return [Hash] a set of data about the processor. Keys in these results:
|
32
|
-
# :family => the family number of the processor
|
33
|
-
# :model => the model number of the processor
|
34
|
-
# :type => what type of processor it is
|
35
|
-
# :step => the stepping of the processor
|
36
|
-
# :model_string => a textual meaning behind the "type" value
|
37
|
-
def model_information
|
38
|
-
processor_type = [
|
39
|
-
"Original OEM Processor",
|
40
|
-
"Intel OverDrive",
|
41
|
-
"Dual Processor"
|
42
|
-
]
|
43
|
-
|
44
|
-
{:family => family, :model => model, :type => type, :step => stepping, :model_string => processor_type[type]}
|
45
|
-
end
|
46
|
-
|
47
|
-
##
|
48
|
-
# The "stepping" of the processor, in number form. Intel term for differentiating processors.
|
49
|
-
#
|
50
|
-
# @return [Fixnum] the stepping of the processor.
|
51
|
-
def stepping; signature & 0xF; end
|
52
|
-
|
53
|
-
##
|
54
|
-
# The "type" of the processor, in number form. Intel term for differentiating processors.
|
55
|
-
# Possible values:
|
56
|
-
#
|
57
|
-
# 0: Original OEM Processor
|
58
|
-
# 1: Intel OverDrive
|
59
|
-
# 2: Dual Processor
|
60
|
-
#
|
61
|
-
# @return [Fixnum] the stepping of the processor.
|
62
|
-
def type; (signature >> 12) & 0x3; end
|
63
|
-
|
64
|
-
##
|
65
|
-
# The full model number of the intel processor.
|
66
|
-
#
|
67
|
-
# @return [Fixnum] the full model number of the processor.
|
68
|
-
def model
|
69
|
-
ext_model = ((signature >> 16) & 0xf)
|
70
|
-
(ext_model << 4) | ((signature >> 3) & 0xf)
|
71
|
-
end
|
72
|
-
|
73
|
-
##
|
74
|
-
# The full family number of the intel processor.
|
75
|
-
#
|
76
|
-
# @return [Fixnum] the full family number of the processor.
|
77
|
-
def family
|
78
|
-
ext_family = (signature >> 20) & 0xff
|
79
|
-
(ext_family << 4) | ((signature >> 8) & 0xf)
|
80
|
-
end
|
81
|
-
|
82
|
-
##
|
83
|
-
# Access the serial number of the processor. Will likely fail, because this feature
|
84
|
-
# was only enabled for the Pentium III line of intel processors and some very
|
85
|
-
# uncommon other manufacturers.
|
86
|
-
#
|
87
|
-
# TODO: raise UnsupportedFunction if PSN is unavailable instead of retrieving PSN = 0
|
88
|
-
#
|
89
|
-
# @return [String] the serial number of the processor, in the format
|
90
|
-
# "XXXX-XXXX-XXXX-XXXX-XXXX-XXXX"
|
91
|
-
def processor_serial_number
|
92
|
-
eax, ebx, ecx, edx = run_function(SERIAL_NUMBER_FN)
|
93
|
-
[signature, edx, ecx].map {|reg| register_to_hex_s(reg)}.join("-")
|
94
|
-
end
|
95
|
-
|
96
|
-
##
|
97
|
-
# Returns the vendor string, available on all processors.
|
98
|
-
# Examples: "GenuineIntel", "AuthenticAMD"
|
99
|
-
#
|
100
|
-
# @return [String] vendor string for the process.
|
101
|
-
def vendor_string
|
102
|
-
eax, ebx, ecx, edx = run_function(VENDOR_ID_FN)
|
103
|
-
register_to_s(ebx) + register_to_s(edx) + register_to_s(ecx)
|
104
|
-
end
|
105
|
-
|
106
|
-
##
|
107
|
-
# Returns the full brand string of the processor
|
108
|
-
#
|
109
|
-
# @example
|
110
|
-
# CPUID.brand_string
|
111
|
-
# #=> "Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz\000"
|
112
|
-
# @return [String] the brand string of the processor
|
113
|
-
def brand_string
|
114
|
-
[BRAND_STR_FN_1, BRAND_STR_FN_2, BRAND_STR_FN_3].map do |fxn|
|
115
|
-
reg_array_to_s(run_function(fxn))
|
116
|
-
end.join
|
117
|
-
end
|
118
|
-
|
119
|
-
##
|
120
|
-
# Returns the number of maximum bits in this processor's virtual address space
|
121
|
-
def virtual_address_size
|
122
|
-
(run_function(ADDRESS_SIZE_FN).first >> 8) & 0xFF
|
123
|
-
end
|
124
|
-
|
125
|
-
##
|
126
|
-
# Returns the number of maximum bits this processor can address in physical memory
|
127
|
-
def physical_address_size
|
128
|
-
run_function(ADDRESS_SIZE_FN).first & 0xFF
|
129
|
-
end
|
130
|
-
|
131
|
-
##
|
132
|
-
# Returns whether the process supports the SYSCALL and SYSRET instructions.
|
133
|
-
#
|
134
|
-
# @return [Boolean]
|
135
|
-
def has_syscall?
|
136
|
-
(run_function(EXT_FEATURE_FN)[3] & INTEL_SYSCALL_CHECK_BIT) > 0
|
137
|
-
end
|
138
|
-
|
139
|
-
##
|
140
|
-
# Returns whether the process supports the SYSCALL and SYSRET instructions.
|
141
|
-
#
|
142
|
-
# @return [Boolean]
|
143
|
-
def has_xd_bit?
|
144
|
-
(run_function(EXT_FEATURE_FN)[3] & INTEL_XD_CHECK_BIT) > 0
|
145
|
-
end
|
146
|
-
|
147
|
-
##
|
148
|
-
# Returns whether the process supports the LAHF and SAHF instructions.
|
149
|
-
#
|
150
|
-
# @return [Boolean]
|
151
|
-
def has_lahf?
|
152
|
-
(run_function(EXT_FEATURE_FN)[2] & INTEL_LAHF_CHECK_BIT) > 0
|
153
|
-
end
|
154
|
-
|
155
|
-
##
|
156
|
-
# Returns whether the processor supports the x86_64 instruction set.
|
157
|
-
#
|
158
|
-
# @return [Boolean] does the processor support x86_64?
|
159
|
-
def has_x64?
|
160
|
-
(run_function(EXT_FEATURE_FN)[3] & INTEL_64_CHECK_BIT) > 0
|
161
|
-
end
|
162
|
-
|
163
|
-
##
|
164
|
-
# Returns whether the processor supports TSC invariance.
|
165
|
-
#
|
166
|
-
# I honestly don't know what this is, but it's in the intel spec.
|
167
|
-
def has_tsc_invariance?
|
168
|
-
(run_function(POWER_MANAGEMENT_FN).last & INTEL_TSC_INVARIANCE_CHECK_BIT) > 0
|
169
|
-
end
|
170
|
-
|
171
|
-
##
|
172
|
-
# Access L2 information via the extended function, 0x80000006.
|
173
|
-
def easy_L2_info
|
174
|
-
ecx = run_function(SIGNATURE_FEATURES_FN)[2]
|
175
|
-
assoc_bits = ((ecx >> 12) & 0xF)
|
176
|
-
assoc = {}
|
177
|
-
case assoc_bits
|
178
|
-
when 0x0
|
179
|
-
assoc[:disabled] = true
|
180
|
-
when 0xF
|
181
|
-
assoc[:fully_associative] = true
|
182
|
-
else
|
183
|
-
assoc[:direct_mapped] = true if assoc_bits & 0x1 > 0
|
184
|
-
assoc[:sixteen_way] = true if assoc_bits & 0x8 > 0
|
185
|
-
assoc[:eight_way] = true if assoc_bits & 0x6 > 0
|
186
|
-
assoc[:four_way] = true if assoc_bits & 0x4 > 0
|
187
|
-
assoc[:two_way] = true if assoc_bits & 0x2 > 0
|
188
|
-
end
|
189
|
-
{:line_size => ecx & 0xFF, :cache_size => (ecx >> 16) * 1024, :associativity => assoc}
|
190
|
-
end
|
15
|
+
###########################################
|
16
|
+
# Support functions for the CPUID module. #
|
17
|
+
###########################################
|
191
18
|
|
192
19
|
#private
|
193
20
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module CPUID
|
2
|
+
module Features
|
3
|
+
SIGNATURE_FEATURES_FN = 1
|
4
|
+
EXT_FEATURE_FN = 0x80000001
|
5
|
+
POWER_MANAGEMENT_FN = 0x80000007
|
6
|
+
|
7
|
+
INTEL_SYSCALL_CHECK_BIT = 1 << 11
|
8
|
+
INTEL_XD_CHECK_BIT = 1 << 20
|
9
|
+
INTEL_64_CHECK_BIT = 1 << 29
|
10
|
+
INTEL_LAHF_CHECK_BIT = 1
|
11
|
+
INTEL_TSC_INVARIANCE_CHECK_BIT = 1 << 7
|
12
|
+
|
13
|
+
def features
|
14
|
+
@features ||= load_features
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def load_features
|
20
|
+
result = {}
|
21
|
+
|
22
|
+
ext_features = run_function(EXT_FEATURE_FN)
|
23
|
+
result[:syscall] = (ext_features[3] & INTEL_SYSCALL_CHECK_BIT) > 0
|
24
|
+
result[:xd_bit] = (ext_features[3] & INTEL_XD_CHECK_BIT) > 0
|
25
|
+
result[:lahf] = (ext_features[2] & INTEL_LAHF_CHECK_BIT) > 0
|
26
|
+
result[:x64] = (ext_features[3] & INTEL_64_CHECK_BIT) > 0
|
27
|
+
|
28
|
+
power_features = run_function(POWER_MANAGEMENT_FN)
|
29
|
+
result[:tsc_invariance] = (power_features.last & INTEL_TSC_INVARIANCE_CHECK_BIT) > 0
|
30
|
+
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(meth, *args, &block)
|
35
|
+
if features.include?(meth)
|
36
|
+
features[meth]
|
37
|
+
elsif meth.to_s[-1,1] == "?" && features.include?(meth.to_s[0..-2].to_sym)
|
38
|
+
features[meth.to_s[0..-2].to_sym]
|
39
|
+
else
|
40
|
+
super(meth, *args, &block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module CPUID
|
2
|
+
module Processor
|
3
|
+
|
4
|
+
VENDOR_ID_FN = 0
|
5
|
+
SIGNATURE_FEATURES_FN = 1
|
6
|
+
SERIAL_NUMBER_FN = 3
|
7
|
+
MAX_EXT_FN = 0x80000000
|
8
|
+
BRAND_STR_FN_1 = 0x80000002
|
9
|
+
BRAND_STR_FN_2 = 0x80000003
|
10
|
+
BRAND_STR_FN_3 = 0x80000004
|
11
|
+
EXT_L2_FN = 0x80000006
|
12
|
+
ADDRESS_SIZE_FN = 0x80000008
|
13
|
+
|
14
|
+
##
|
15
|
+
# Returns the model information of the processor, which can be used
|
16
|
+
# for telling individual processors apart. Note: you will need to use
|
17
|
+
# cache information as well to tell some processors apart.
|
18
|
+
#
|
19
|
+
# @return [Hash] a set of data about the processor. Keys in these results:
|
20
|
+
# :family => the family number of the processor
|
21
|
+
# :model => the model number of the processor
|
22
|
+
# :type => what type of processor it is
|
23
|
+
# :step => the stepping of the processor
|
24
|
+
# :model_string => a textual meaning behind the "type" value
|
25
|
+
def model_information
|
26
|
+
processor_type = [
|
27
|
+
"Original OEM Processor",
|
28
|
+
"Intel OverDrive",
|
29
|
+
"Dual Processor"
|
30
|
+
]
|
31
|
+
|
32
|
+
{:family => family, :model => model, :type => type, :step => stepping, :model_string => processor_type[type]}
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Is the processor an Intel-made processor?
|
37
|
+
def intel?
|
38
|
+
vendor_string == "GenuineIntel"
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Is the process an AMD-made processor?
|
43
|
+
def amd?
|
44
|
+
vendor_string == "AuthenticAMD"
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# The "stepping" of the processor, in number form. Intel term for differentiating processors.
|
49
|
+
#
|
50
|
+
# @return [Fixnum] the stepping of the processor.
|
51
|
+
def stepping; signature & 0xF; end
|
52
|
+
|
53
|
+
##
|
54
|
+
# The "type" of the processor, in number form. Intel term for differentiating processors.
|
55
|
+
# Possible values:
|
56
|
+
#
|
57
|
+
# 0: Original OEM Processor
|
58
|
+
# 1: Intel OverDrive
|
59
|
+
# 2: Dual Processor
|
60
|
+
#
|
61
|
+
# @return [Fixnum] the stepping of the processor.
|
62
|
+
def type; (signature >> 12) & 0x3; end
|
63
|
+
|
64
|
+
##
|
65
|
+
# The full model number of the intel processor.
|
66
|
+
#
|
67
|
+
# @return [Fixnum] the full model number of the processor.
|
68
|
+
def model
|
69
|
+
ext_model = ((signature >> 16) & 0xf)
|
70
|
+
(ext_model << 4) | ((signature >> 3) & 0xf)
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# The full family number of the intel processor.
|
75
|
+
#
|
76
|
+
# @return [Fixnum] the full family number of the processor.
|
77
|
+
def family
|
78
|
+
ext_family = (signature >> 20) & 0xff
|
79
|
+
(ext_family << 4) | ((signature >> 8) & 0xf)
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Access the serial number of the processor. Will likely fail, because this feature
|
84
|
+
# was only enabled for the Pentium III line of intel processors and some very
|
85
|
+
# uncommon other manufacturers.
|
86
|
+
#
|
87
|
+
# TODO: raise UnsupportedFunction if PSN is unavailable instead of retrieving PSN = 0
|
88
|
+
#
|
89
|
+
# @return [String] the serial number of the processor, in the format
|
90
|
+
# "XXXX-XXXX-XXXX-XXXX-XXXX-XXXX"
|
91
|
+
def processor_serial_number
|
92
|
+
eax, ebx, ecx, edx = run_function(SERIAL_NUMBER_FN)
|
93
|
+
[signature, edx, ecx].map {|reg| register_to_hex_s(reg)}.join("-")
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Returns the vendor string, available on all processors.
|
98
|
+
# Examples: "GenuineIntel", "AuthenticAMD"
|
99
|
+
#
|
100
|
+
# @return [String] vendor string for the process.
|
101
|
+
def vendor_string
|
102
|
+
eax, ebx, ecx, edx = run_function(VENDOR_ID_FN)
|
103
|
+
register_to_s(ebx) + register_to_s(edx) + register_to_s(ecx)
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# Returns the full brand string of the processor
|
108
|
+
#
|
109
|
+
# @example
|
110
|
+
# CPUID.brand_string
|
111
|
+
# #=> "Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz\000"
|
112
|
+
# @return [String] the brand string of the processor
|
113
|
+
def brand_string
|
114
|
+
[BRAND_STR_FN_1, BRAND_STR_FN_2, BRAND_STR_FN_3].map do |fxn|
|
115
|
+
reg_array_to_s(run_function(fxn))
|
116
|
+
end.join
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# Returns the number of maximum bits in this processor's virtual address space
|
121
|
+
def virtual_address_size
|
122
|
+
(run_function(ADDRESS_SIZE_FN).first >> 8) & 0xFF
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Returns the number of maximum bits this processor can address in physical memory
|
127
|
+
def physical_address_size
|
128
|
+
run_function(ADDRESS_SIZE_FN).first & 0xFF
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Access L2 information via the extended function, 0x80000006.
|
133
|
+
def easy_L2_info
|
134
|
+
ecx = run_function(SIGNATURE_FEATURES_FN)[2]
|
135
|
+
assoc_bits = ((ecx >> 12) & 0xF)
|
136
|
+
assoc = {}
|
137
|
+
case assoc_bits
|
138
|
+
when 0x0
|
139
|
+
assoc[:disabled] = true
|
140
|
+
when 0xF
|
141
|
+
assoc[:fully_associative] = true
|
142
|
+
else
|
143
|
+
assoc[:direct_mapped] = true if assoc_bits & 0x1 > 0
|
144
|
+
assoc[:sixteen_way] = true if assoc_bits & 0x8 > 0
|
145
|
+
assoc[:eight_way] = true if assoc_bits & 0x6 > 0
|
146
|
+
assoc[:four_way] = true if assoc_bits & 0x4 > 0
|
147
|
+
assoc[:two_way] = true if assoc_bits & 0x2 > 0
|
148
|
+
end
|
149
|
+
{:line_size => ecx & 0xFF, :cache_size => (ecx >> 16) * 1024, :associativity => assoc}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
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.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Edgar
|
@@ -43,6 +43,8 @@ files:
|
|
43
43
|
- ext/cpuid/cpuid_ext/extconf.rb
|
44
44
|
- lib/cpuid.rb
|
45
45
|
- lib/cpuid/cpuid.rb
|
46
|
+
- lib/cpuid/features.rb
|
47
|
+
- lib/cpuid/processor.rb
|
46
48
|
- test/helper.rb
|
47
49
|
- test/test_cpuid.rb
|
48
50
|
has_rdoc: true
|