Skip to content

Commit d57cb3e

Browse files
committed
feat: ✨ fixes Add missing Meltdown / Spectre related CPU flags #69
1 parent 17ba2d4 commit d57cb3e

File tree

2 files changed

+69
-36
lines changed

2 files changed

+69
-36
lines changed

lib/fog/proxmox/helpers/cpu_helper.rb

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,59 @@ module Fog
2121
module Proxmox
2222
# module Cpu mixins
2323
module CpuHelper
24-
CPU_REGEXP = /(\bcputype=)?([\w-]+)[,]?(\bflags=)?(\+[\w-]+)?[;]?(\+[\w-]+)?/
25-
def self.extract(cpu,i)
26-
cpu ? CPU_REGEXP.match(cpu.to_s)[i] : ''
24+
CPU_REGEXP = /(\bcputype=)?(?<cputype>[\w-]+)[,]?(\bflags=)?(?<flags>[[\+\-][\w-]+[;]?]*)/
25+
FLAGS = { spectre: 'spec-ctrl', pcid: 'pcid', ssbd: 'ssbd', ibpb: 'ibpb', virt_ssbd: 'virt-ssbd', amd_ssbd: 'amd-ssbd', amd_no_ssb: 'amd-no-ssb', md_clear: 'md-clear', pdpe1gb: 'pdpe1gb', hv_tlbflush: 'hv-tlbflush', aes: 'aes', hv_evmcs: 'hv-evmcs' }
26+
def self.flags
27+
FLAGS
28+
end
29+
30+
def self.extract(cpu, name)
31+
captures_h = cpu ? CPU_REGEXP.match(cpu.to_s) : { cputype: '', flags: '' }
32+
captures_h[name]
33+
end
34+
35+
def self.extract_cputype(cpu)
36+
extract(cpu, :cputype)
37+
end
38+
39+
def self.extract_flags(cpu)
40+
extract(cpu, :flags)
2741
end
2842

29-
def self.extract_type(cpu)
30-
extract(cpu,2)
43+
def self.flag_value(cpu, flag_key)
44+
flag_value = '0'
45+
raw_values = extract_flags(cpu).split(';').select { |flag| ['+' + flag_key, '-' + flag_key].include?(flag) }
46+
unless raw_values.empty?
47+
flag_value = raw_values[0].start_with?('+') ? '+1' : raw_values[0].start_with?('-') ? '-1' : '0'
48+
end
49+
flag_value
3150
end
3251

33-
def self.has_pcid?(cpu)
34-
extract(cpu,5) == '+pcid'
52+
def self.hash_has_no_default_flag?(cpu_h, flag_name)
53+
cpu_h.key?(flag_name) && ['-1', '+1'].include?(cpu_h[flag_name])
3554
end
3655

37-
def self.has_spectre?(cpu)
38-
extract(cpu,4) == '+spec-ctrl'
56+
def self.hash_flag(cpu_h, flag_name)
57+
flag = ''
58+
if cpu_h.key?(flag_name)
59+
flag = '+' if cpu_h[flag_name] == '+1'
60+
flag = '-' if cpu_h[flag_name] == '-1'
61+
end
62+
flag
3963
end
4064

4165
def self.flatten(cpu_h)
42-
return {} unless cpu_h['cpu_type']
66+
return '' unless cpu_h['cpu_type']
4367

4468
cpu_type = "cputype=#{cpu_h['cpu_type']}"
45-
spectre = cpu_h['spectre'].to_i == 1
46-
pcid = cpu_h['pcid'].to_i == 1
47-
cpu_type += ',flags=' if spectre || pcid
48-
cpu_type += '+spec-ctrl' if spectre
49-
cpu_type += ';' if spectre && pcid
50-
cpu_type += '+pcid' if pcid
69+
num_flags = 0
70+
FLAGS.each_key { |flag_key| num_flags += 1 if hash_has_no_default_flag?(cpu_h, flag_key.to_s) }
71+
cpu_type += ',flags=' if num_flags > 0
72+
flags_with_no_default_value = FLAGS.select { |flag_key, _flag_value| hash_has_no_default_flag?(cpu_h, flag_key.to_s) }
73+
flags_with_no_default_value.each_with_index do |(flag_key, flag_value), index|
74+
cpu_type += hash_flag(cpu_h, flag_key.to_s) + flag_value if hash_has_no_default_flag?(cpu_h, flag_key.to_s)
75+
cpu_type += ';' if num_flags > index + 1
76+
end
5177
cpu_type
5278
end
5379
end

spec/helpers/cpu_helper_spec.rb

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,48 +23,55 @@
2323
describe Fog::Proxmox::CpuHelper do
2424

2525
let(:cpu) do
26-
'cputype=Skylake-Client,flags=+spec-ctrl;+pcid'
26+
'cputype=Skylake-Client,flags=+spec-ctrl;+pcid;+ssbd;-aes'
2727
end
2828
let(:cpu_nocputype) do
29-
'kvm64,flags=+spec-ctrl;+pcid'
29+
'kvm64,flags=+spec-ctrl;+pcid;+ssbd'
3030
end
3131
let(:cpu_nospectre) do
3232
'cputype=kvm64,flags=+pcid'
3333
end
3434
let(:cpu_nopcid) do
3535
'cputype=kvm64,flags=+spec-ctrl'
3636
end
37+
let(:cpu_nossbd) do
38+
'cputype=kvm64,flags=+pcid'
39+
end
3740

38-
describe '#extract_type' do
41+
describe '#extract_cputype' do
3942
it "returns string" do
40-
result = Fog::Proxmox::CpuHelper.extract_type(cpu)
43+
result = Fog::Proxmox::CpuHelper.extract_cputype(cpu)
4144
assert_equal('Skylake-Client', result)
4245
end
4346
it "returns string" do
44-
result = Fog::Proxmox::CpuHelper.extract_type(cpu_nocputype)
47+
result = Fog::Proxmox::CpuHelper.extract_cputype(cpu_nocputype)
4548
assert_equal('kvm64', result)
4649
end
4750
end
4851

49-
describe '#has_spectre?' do
50-
it "returns true" do
51-
result = Fog::Proxmox::CpuHelper.has_spectre?(cpu)
52-
assert result
52+
describe '#flag_value' do
53+
it "returns +1" do
54+
result = Fog::Proxmox::CpuHelper.flag_value(cpu, 'spec-ctrl')
55+
assert_equal('+1', result)
5356
end
54-
it "returns false" do
55-
result = Fog::Proxmox::CpuHelper.has_spectre?(cpu_nospectre)
56-
assert !result
57+
it "returns -1" do
58+
result = Fog::Proxmox::CpuHelper.flag_value(cpu, 'aes')
59+
assert_equal('-1', result)
60+
end
61+
it "returns 0" do
62+
result = Fog::Proxmox::CpuHelper.flag_value(cpu, 'amd-ssbd')
63+
assert_equal('0', result)
5764
end
5865
end
59-
60-
describe '#has_pcid?' do
61-
it "returns true" do
62-
result = Fog::Proxmox::CpuHelper.has_pcid?(cpu)
63-
assert result
66+
67+
describe '#flatten ' do
68+
it "returns cputype=kvm64,flags=+pcid;+ibpb;-hv-tlbflush" do
69+
result = Fog::Proxmox::CpuHelper.flatten("cpu_type"=>"kvm64", "spectre"=>"0", "pcid"=>"+1", "ssbd"=>"0", "ibpb"=>"+1", "virt_ssbd"=>"0", "amd_ssbd"=>"0", "amd_no_ssb"=>"0", "md_clear"=>"0", "pdpe1gb"=>"0", "hv_tlbflush"=>"-1", "aes"=>"0", "hv_evmcs"=>"0")
70+
assert_equal('cputype=kvm64,flags=+pcid;+ibpb;-hv-tlbflush', result)
6471
end
65-
it "returns false" do
66-
result = Fog::Proxmox::CpuHelper.has_pcid?(cpu_nopcid)
67-
assert !result
72+
it "returns cputype=Skylake-Client,flags=+spec-ctrl;+pcid;+amd-no-ssbd'" do
73+
result = Fog::Proxmox::CpuHelper.flatten('cpu_type' => 'Skylake-Client', 'pcid' => '+1', 'spectre' => '+1', 'amd_no_ssb' => '-1')
74+
assert_equal('cputype=Skylake-Client,flags=+spec-ctrl;+pcid;-amd-no-ssb', result)
6875
end
6976
end
7077
end

0 commit comments

Comments
 (0)