\chapter{评测}\label{sec:eval}

\section{评测环境}

本文对 gem5 模拟器修改，对以下 5 种配置进行评测：Baseline, Fence,
Fence+DIFT, IS, IS+DIFT. Baseline 表示受 Spectre 攻击影响的处理器模型，
Fence 和 IS 分别表示对所有推测式执行中的 load 指令，推迟执行和用
InvisiSpec的方案执行，Fence+DIFT 和 IS+DIFT 则是使用动态信息流追踪识别
可能泄露秘密数据的 load，只对这些 load 使用相应的安全的执行方案。

对所有的处理器配置，基本配置如下：

\begin{tabular}{|c|c|}
\hline 
参数 & 配置 \tabularnewline
\hline 
\hline 
指令系统 & x86\_64\tabularnewline
\hline 
处理器类型 & 8发射乱序处理器\tabularnewline
\hline 
ROB & 192\tabularnewline
\hline 
LDQ & 32\tabularnewline
\hline 
STQ & 32\tabularnewline
\hline 
发射队列 & 64\tabularnewline
\hline 
L1 I-Cache & 32KB, 4路组相联, 1周期延迟\tabularnewline
\hline 
L1 D-Cache & 64KB, 8路组相联, 1周期延迟\tabularnewline
\hline 
L2 Cache & 2MB, 16路组相联, 8周期延迟\tabularnewline
\hline 
\end{tabular}

\section{评测指标}

\section{评测结果}

\subsection{微架构安全性测试}

本文构造一个测试程序对每种配置的处理器进行安全性的测试，用于验证实现的
方案可以防御 Spectre 攻击。

由于 gem5 的 Ruby 存储模型不支持 clflush 指令，因此测试程序使用
Evict+Reload 的方式进行攻击。由于配置的系统末级缓存为 2MB，可以对一个
2MB 的存储区域进行访问，以清除缓存内原有内容。

具体代码如下：

\begin{minted}{C}
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <x86intrin.h>

/* default: 64B line size, L1-D 64KB assoc 2, L1-I 32KB assoc 2, L2 2MB assoc 8 */
#define LLC_SIZE (2 << 20)

uint8_t dummy[LLC_SIZE];
size_t array_size = 4;
uint8_t array1[200] = {1, 2, 3, 4};
uint8_t array2[256 * 64 * 2];
uint8_t X;
uint8_t array3[4096];
uint8_t tmp;

uint8_t victim(size_t idx)
{
	if (idx < array_size) {
		return array2[array1[idx] * 64];
	}
	return 0;
}

int main()
{
	unsigned long t[256];
	volatile uint8_t x;

	victim(0);
	victim(0);
	victim(0);
	victim(0);
	victim(0);

	memset(dummy, 1, sizeof(dummy)); // flush L2
	X = 123; // set the secret value, and also bring it to cache

	_mm_mfence();

	size_t attack_idx = &X - array1;
	victim(attack_idx);

	for (int i = 0; i < 256; i++) {
		unsigned int junk;
		unsigned long time1 = __rdtscp(&junk);
		x ^= array2[i * 64];
		unsigned long time2 = __rdtscp(&junk);
		t[i] = time2 - time1;
	}

	printf("attack_idx = %ld\n", attack_idx);
	for (int i = 0; i < 256; i++) {
		printf("%d: %d, %s\n", i, t[i], (t[i] < 40)? "hit": "miss");
	}
}
\end{minted}

在以上代码中，攻击者要通过受害者执行的函数 victim 的推测式执行泄露
victim 在正常执行中无法访问的 X 的值。攻击者先训练 victim 的分支预测器，
清除缓存中原有的内容，之后我们设置 X 为 123，然后攻击者再让 victim 执
行访问 X，最后扫描 array2 检查其中是否有元素在缓存中命中。

在 Baseline 配置中，执行上述程序，可以看到 \verb|array2[123 * 64]| 在
缓存中命中，在 array2 的其他位置缓存缺失，从而攻击者可以通过 Spectre
攻击得到 X 的值 123. 而在其他配置中，array2 的所有位置都发生缓存缺失，
从而攻击者无法得出 X 的值，说明这些配置都能防御 Spectre 攻击。

\subsection{SPEC CPU2006的性能评测}

本文对 21 个 SPEC CPU2006 基准测试进行评测，基准测试的数据集使用 ref
集。先用 gem5 的 AtomicSimpleCPU 运行 10000000000 条指令，再用待评测的
处理器配置运行 1000000000 条指令，得出评测结果。

\begin{figure}[htbp]
  \centering
  \includegraphics[width=0.8\textwidth]{result.eps}
\end{figure}

从评测结果可以看出，在使用 DIFT 识别可能泄露数据的 load 指令后，推迟这
些指令的执行，有 15\% 的性能开销，平均性能开销比 InvisiSpec 小。在此基
础上，用 InvisiSpec 的方案执行这些 load 指令，可以进一步将性能开销减少
至 8.5\%.
