Skip to content

Commit

Permalink
feat: ✨ fixes Add missing Meltdown / Spectre related CPU flags #69
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanrobert committed Feb 23, 2021
1 parent 17ba2d4 commit d57cb3e
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 36 deletions.
58 changes: 42 additions & 16 deletions lib/fog/proxmox/helpers/cpu_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,59 @@ module Fog
module Proxmox
# module Cpu mixins
module CpuHelper
CPU_REGEXP = /(\bcputype=)?([\w-]+)[,]?(\bflags=)?(\+[\w-]+)?[;]?(\+[\w-]+)?/
def self.extract(cpu,i)
cpu ? CPU_REGEXP.match(cpu.to_s)[i] : ''
CPU_REGEXP = /(\bcputype=)?(?<cputype>[\w-]+)[,]?(\bflags=)?(?<flags>[[\+\-][\w-]+[;]?]*)/
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' }
def self.flags
FLAGS
end

def self.extract(cpu, name)
captures_h = cpu ? CPU_REGEXP.match(cpu.to_s) : { cputype: '', flags: '' }
captures_h[name]
end

def self.extract_cputype(cpu)
extract(cpu, :cputype)
end

def self.extract_flags(cpu)
extract(cpu, :flags)
end

def self.extract_type(cpu)
extract(cpu,2)
def self.flag_value(cpu, flag_key)
flag_value = '0'
raw_values = extract_flags(cpu).split(';').select { |flag| ['+' + flag_key, '-' + flag_key].include?(flag) }
unless raw_values.empty?
flag_value = raw_values[0].start_with?('+') ? '+1' : raw_values[0].start_with?('-') ? '-1' : '0'
end
flag_value
end

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

def self.has_spectre?(cpu)
extract(cpu,4) == '+spec-ctrl'
def self.hash_flag(cpu_h, flag_name)
flag = ''
if cpu_h.key?(flag_name)
flag = '+' if cpu_h[flag_name] == '+1'
flag = '-' if cpu_h[flag_name] == '-1'
end
flag
end

def self.flatten(cpu_h)
return {} unless cpu_h['cpu_type']
return '' unless cpu_h['cpu_type']

cpu_type = "cputype=#{cpu_h['cpu_type']}"
spectre = cpu_h['spectre'].to_i == 1
pcid = cpu_h['pcid'].to_i == 1
cpu_type += ',flags=' if spectre || pcid
cpu_type += '+spec-ctrl' if spectre
cpu_type += ';' if spectre && pcid
cpu_type += '+pcid' if pcid
num_flags = 0
FLAGS.each_key { |flag_key| num_flags += 1 if hash_has_no_default_flag?(cpu_h, flag_key.to_s) }
cpu_type += ',flags=' if num_flags > 0
flags_with_no_default_value = FLAGS.select { |flag_key, _flag_value| hash_has_no_default_flag?(cpu_h, flag_key.to_s) }
flags_with_no_default_value.each_with_index do |(flag_key, flag_value), index|
cpu_type += hash_flag(cpu_h, flag_key.to_s) + flag_value if hash_has_no_default_flag?(cpu_h, flag_key.to_s)
cpu_type += ';' if num_flags > index + 1
end
cpu_type
end
end
Expand Down
47 changes: 27 additions & 20 deletions spec/helpers/cpu_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,48 +23,55 @@
describe Fog::Proxmox::CpuHelper do

let(:cpu) do
'cputype=Skylake-Client,flags=+spec-ctrl;+pcid'
'cputype=Skylake-Client,flags=+spec-ctrl;+pcid;+ssbd;-aes'
end
let(:cpu_nocputype) do
'kvm64,flags=+spec-ctrl;+pcid'
'kvm64,flags=+spec-ctrl;+pcid;+ssbd'
end
let(:cpu_nospectre) do
'cputype=kvm64,flags=+pcid'
end
let(:cpu_nopcid) do
'cputype=kvm64,flags=+spec-ctrl'
end
let(:cpu_nossbd) do
'cputype=kvm64,flags=+pcid'
end

describe '#extract_type' do
describe '#extract_cputype' do
it "returns string" do
result = Fog::Proxmox::CpuHelper.extract_type(cpu)
result = Fog::Proxmox::CpuHelper.extract_cputype(cpu)
assert_equal('Skylake-Client', result)
end
it "returns string" do
result = Fog::Proxmox::CpuHelper.extract_type(cpu_nocputype)
result = Fog::Proxmox::CpuHelper.extract_cputype(cpu_nocputype)
assert_equal('kvm64', result)
end
end

describe '#has_spectre?' do
it "returns true" do
result = Fog::Proxmox::CpuHelper.has_spectre?(cpu)
assert result
describe '#flag_value' do
it "returns +1" do
result = Fog::Proxmox::CpuHelper.flag_value(cpu, 'spec-ctrl')
assert_equal('+1', result)
end
it "returns false" do
result = Fog::Proxmox::CpuHelper.has_spectre?(cpu_nospectre)
assert !result
it "returns -1" do
result = Fog::Proxmox::CpuHelper.flag_value(cpu, 'aes')
assert_equal('-1', result)
end
it "returns 0" do
result = Fog::Proxmox::CpuHelper.flag_value(cpu, 'amd-ssbd')
assert_equal('0', result)
end
end

describe '#has_pcid?' do
it "returns true" do
result = Fog::Proxmox::CpuHelper.has_pcid?(cpu)
assert result
describe '#flatten ' do
it "returns cputype=kvm64,flags=+pcid;+ibpb;-hv-tlbflush" do
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")
assert_equal('cputype=kvm64,flags=+pcid;+ibpb;-hv-tlbflush', result)
end
it "returns false" do
result = Fog::Proxmox::CpuHelper.has_pcid?(cpu_nopcid)
assert !result
it "returns cputype=Skylake-Client,flags=+spec-ctrl;+pcid;+amd-no-ssbd'" do
result = Fog::Proxmox::CpuHelper.flatten('cpu_type' => 'Skylake-Client', 'pcid' => '+1', 'spectre' => '+1', 'amd_no_ssb' => '-1')
assert_equal('cputype=Skylake-Client,flags=+spec-ctrl;+pcid;-amd-no-ssb', result)
end
end
end

0 comments on commit d57cb3e

Please sign in to comment.