Skip to content

Commit

Permalink
Add SMI detection accuracy improvements
Browse files Browse the repository at this point in the history
Signed-off-by: Carles Pey <[email protected]>
  • Loading branch information
cpey committed Oct 16, 2024
1 parent 7f4df2d commit d55cc4c
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
26 changes: 23 additions & 3 deletions chipsec/modules/tools/smm/smm_ptr.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@
# be long-running
OUTLIER_THRESHOLD = 33.3

# Scan mode delay before retry
SCAN_MODE_RETRY_DELAY = 0.01

# SMI count MSR
MSR_SMI_COUNT = 0x00000034

Expand Down Expand Up @@ -262,7 +265,7 @@ def add(self, duration, code, data, gprs, confirmed=False):
self.max.update(duration, code, data, gprs.copy())
elif duration < self.min.duration:
self.min.update(duration, code, data, gprs.copy())
else:
elif self.is_slow_outlier(duration):
self.outliers += 1
self.outliers_hist += 1
self.outlier.update(duration, code, data, gprs.copy())
Expand All @@ -277,15 +280,31 @@ def avg(self):
self.acc_smi_duration = 0
self.acc_smi_num = 0

def is_outlier(self, value):
self.avg()
def is_slow_outlier(self, value):
ret = False
if self.avg_smi_duration and value > self.avg_smi_duration * (1 + OUTLIER_THRESHOLD / 100):
ret = True
if self.hist_smi_duration and value > self.hist_smi_duration * (1 + OUTLIER_THRESHOLD / 100):
ret = True
return ret

def is_fast_outlier(self, value):
ret = False
if self.avg_smi_duration and value < self.avg_smi_duration * (1 - OUTLIER_THRESHOLD / 100):
ret = True
if self.hist_smi_duration and value < self.hist_smi_duration * (1 - OUTLIER_THRESHOLD / 100):
ret = True
return ret

def is_outlier(self, value):
self.avg()
ret = False
if self.is_slow_outlier(value):
ret = True
if self.is_fast_outlier(value):
ret = True
return ret

def skip(self):
return self.outliers or self.confirmed

Expand Down Expand Up @@ -487,6 +506,7 @@ def smi_fuzz_iter(self, thread_id, _addr, _smi_desc, fill_contents=True, restore
# Re-do the call if it was identified as an outlier, due to periodic SMI delays
#
if scan.is_outlier(duration):
time.sleep(SCAN_MODE_RETRY_DELAY)
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():
Expand Down
3 changes: 2 additions & 1 deletion drivers/linux/amd64/cpu.asm
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
global __cpuid__
global __swsmi__
global __swsmi_timed__
global __swsmi_timed_test__

section .text

Expand Down Expand Up @@ -463,6 +462,8 @@ __swsmi_timed__:
ror ax, 8
out 0B3h, al

wbinvd
mfence
; read time-stamp counter
mov r9, rax
mov r11, rdx
Expand Down
3 changes: 3 additions & 0 deletions drivers/linux/chipsec_km.c
Original file line number Diff line number Diff line change
Expand Up @@ -1114,9 +1114,12 @@ static long d_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioc
break;
}

unsigned long flags;
unsigned long m_time;
preempt_disable();
local_irq_save(flags);
__swsmi_timed__((SMI_CTX *)ptr, &m_time);
local_irq_restore(flags);
preempt_enable();
ptrbuf[numargs] = m_time;

Expand Down

0 comments on commit d55cc4c

Please sign in to comment.