FILE
speculation.rst
File preview with syntax highlighting.
linux-6.19.14/Documentation/translations/zh_CN/staging/speculation.rst
1.. SPDX-License-Identifier: GPL-2.0 2.. include:: ../disclaimer-zh_CN.rst 3 4:Original: Documentation/staging/speculation.rst 5 6:翻译: 7 8 崔巍 Cui Wei <chris.wei.cui@gmail.com> 9 10======== 11推测执行 12======== 13 14本文档解释了推测执行的潜在影响,以及如何使用通用API来减轻不良影响。 15 16------------------------------------------------------------------------------ 17 18为提高性能并减少平均延迟,许多现代处理器都采用分支预测等推测执行技术,执行结果 19可能在后续阶段被丢弃。 20 21通常情况下,我们无法从架构状态(如寄存器内容)观察到推测执行。然而,在某些情况 22下从微架构状态观察其影响是可能的,例如数据是否存在于缓存中。这种状态可能会形成 23侧信道,通过观察侧信道可以提取秘密信息。 24 25例如,在分支预测存在的情况下,边界检查可能被推测执行的代码忽略。考虑以下代码:: 26 27 int load_array(int *array, unsigned int index) 28 { 29 if (index >= MAX_ARRAY_ELEMS) 30 return 0; 31 else 32 return array[index]; 33 } 34 35在arm64上,可以编译成如下汇编序列:: 36 37 CMP <index>, #MAX_ARRAY_ELEMS 38 B.LT less 39 MOV <returnval>, #0 40 RET 41 less: 42 LDR <returnval>, [<array>, <index>] 43 RET 44 45处理器有可能误预测条件分支,并推测性装载array[index],即使index >= MAX_ARRAY_ELEMS。 46这个值随后会被丢弃,但推测的装载可能会影响微架构状态,随后可被测量到。 47 48涉及多个依赖内存访问的更复杂序列可能会导致敏感信息泄露。以前面的示例为基础,考虑 49以下代码:: 50 51 int load_dependent_arrays(int *arr1, int *arr2, int index) 52 { 53 int val1, val2, 54 55 val1 = load_array(arr1, index); 56 val2 = load_array(arr2, val1); 57 58 return val2; 59 } 60 61根据推测,对load_array()的第一次调用可能会返回一个越界地址的值,而第二次调用将影响 62依赖于该值的微架构状态。这可能会提供一个任意读取原语。 63 64缓解推测执行侧信道 65================== 66 67内核提供了一个通用API以确保即使在推测情况下也能遵守边界检查。受推测执行侧信道影响 68的架构应当实现这些原语。 69 70<linux/nospec.h>中的array_index_nospec()辅助函数可用于防止信息通过侧信道泄漏。 71 72调用array_index_nospec(index, size)将返回一个经过净化的索引值,即使在CPU推测执行 73条件下,该值也会被严格限制在[0, size)范围内。 74 75这可以用来保护前面的load_array()示例:: 76 77 int load_array(int *array, unsigned int index) 78 { 79 if (index >= MAX_ARRAY_ELEMS) 80 return 0; 81 else { 82 index = array_index_nospec(index, MAX_ARRAY_ELEMS); 83 return array[index]; 84 } 85 }
~/
Read-only file preview.