Skip to content

Commit

Permalink
smm_ptr: Add SMI contention check to the scan mode
Browse files Browse the repository at this point in the history
Signed-off-by: Carles Pey <[email protected]>
  • Loading branch information
cpey authored and npmitche committed Jul 16, 2024
1 parent 1eae6e0 commit 9f84aba
Showing 1 changed file with 48 additions and 6 deletions.
54 changes: 48 additions & 6 deletions chipsec/modules/tools/smm/smm_ptr.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,15 @@

import struct
import os
import sys

from chipsec.module_common import BaseModule
from chipsec.library.returncode import ModuleResult
from chipsec.library.file import write_file
from chipsec.library.logger import print_buffer_bytes
from chipsec.hal.interrupts import Interrupts
from chipsec.library.exceptions import BadSMIDetected
from chipsec.helper.oshelper import OsHelper


#################################################################
Expand Down Expand Up @@ -146,6 +148,9 @@
# be long-running
OUTLIER_THRESHOLD = 33.3

# SMI count MSR
MSR_SMI_COUNT = 0x00000034

#
# Defaults
#
Expand Down Expand Up @@ -195,6 +200,37 @@ def __init__(self):
self.hist_smi_duration = 0
self.hist_smi_num = 0
self.outliers_hist = 0
self.helper = OsHelper().get_default_helper()
self.helper.init()
self.smi_count = self.get_smi_count()

def __del__(self):
self.helper.close()

def get_smi_count(self):
count = -1
#
# The SMI count is the same on all CPUs
#
cpu = 0
try:
count = self.helper.read_msr(cpu, MSR_SMI_COUNT)
count = count[1] << 32 | count[0]
except UnimplementedAPIError:
pass
return count

def valid_smi_count(self):
valid = False
count = self.get_smi_count()
if (count == -1):
return True
elif (count == self.smi_count + 1):
valid = True
self.smi_count = count
if not valid:
print("SMI contention detected", file=sys.stderr)
return valid

def find_address_in_regs(self, gprs):
for key, value in gprs.items():
Expand All @@ -204,9 +240,9 @@ def find_address_in_regs(self, gprs):
return key

def clear(self):
self.max = smi_info(0);
self.min = smi_info(2**32-1);
self.outlier = smi_info(0);
self.max = smi_info(0)
self.min = smi_info(2**32-1)
self.outlier = smi_info(0)
self.acc_smi_duration = 0
self.acc_smi_num = 0
self.avg_smi_duration = 0
Expand Down Expand Up @@ -360,7 +396,7 @@ def send_smi_timed(self, thread_id, smi_code, smi_data, name, desc, rax, rbx, rc
self.logger.log(f' RSI: 0x{rsi:016X}')
self.logger.log(f' RDI: 0x{rdi:016X}')
ret = self.interrupts.send_SW_SMI_timed(thread_id, smi_code, smi_data, rax, rbx, rcx, rdx, rsi, rdi)
duration = ret[7];
duration = ret[7]
return (True, duration)

def check_memory(self, _addr, _smi_desc, fn, restore_contents=False):
Expand Down Expand Up @@ -443,12 +479,18 @@ def smi_fuzz_iter(self, thread_id, _addr, _smi_desc, fill_contents=True, restore
if not scan:
self.send_smi(thread_id, _smi_desc.smi_code, _smi_desc.smi_data, _smi_desc.name, _smi_desc.desc, _rax, _rbx, _rcx, _rdx, _rsi, _rdi)
else:
_, duration = self.send_smi_timed(thread_id, _smi_desc.smi_code, _smi_desc.smi_data, _smi_desc.name, _smi_desc.desc, _rax, _rbx, _rcx, _rdx, _rsi, _rdi)
while True:
_, duration = self.send_smi_timed(thread_id, _smi_desc.smi_code, _smi_desc.smi_data, _smi_desc.name, _smi_desc.desc, _rax, _rbx, _rcx, _rdx, _rsi, _rdi)
if scan.valid_smi_count():
break
#
# Re-do the call if it was identified as an outlier, due to periodic SMI delays
#
if scan.is_outlier(duration):
_, duration = self.send_smi_timed(thread_id, _smi_desc.smi_code, _smi_desc.smi_data, _smi_desc.name, _smi_desc.desc, _rax, _rbx, _rcx, _rdx, _rsi, _rdi)
while True:
_, duration = self.send_smi_timed(thread_id, _smi_desc.smi_code, _smi_desc.smi_data, _smi_desc.name, _smi_desc.desc, _rax, _rbx, _rcx, _rdx, _rsi, _rdi)
if scan.valid_smi_count():
break
#
# Check memory buffer if not in 'No Fill' mode
#
Expand Down

0 comments on commit 9f84aba

Please sign in to comment.