使用间接控制流指令的推测的制作方法

文档序号:23068012发布日期:2020-11-25 17:55阅读:93来源:国知局
使用间接控制流指令的推测的制作方法

相关申请的交叉引用

本申请引用了于2018年7月6日提交的题为“indirectcontrolflowinstructionsandinhibitingdatavaluespeculation(间接控制流指令和禁止数据值推测)”的专利申请gb1811151,其由richardearnshaw、kristofbeyls和jamesgreenhalgh发明并转让给arm有限公司,其内容以引用方式结合于此。

本技术涉及数据处理。具体地,本技术与推测性执行领域相关。



背景技术:

推测性执行是一种在知道是否应执行一系列指令之前执行这些指令的技术。在稍后的某个时间点,确定是否应该执行推测性地执行的指令。如果是,则过程继续。如果不是,则执行“倒带(rewound)”。这种推测形式被称为控制流推测。在一些情况下,已经发现此类推测性执行会导致安全漏洞。例如,可以使处理器推测性地执行特权代码,以将加密数据不必要地加载到缓存中。由于在倒带后可能无法清除缓存,因此可以使用边信道攻击来探测所请求的数据。另一种推测形式是数据值推测,其中在已知指令的所有输入之前推测由该指令产生的结果值。

本技术认识到期望在发生控制流推测的地方保持数据安全。



技术实现要素:

从第一示例配置来看,提供了一种设备,所述设备包括:输入电路,用于接收输入数据;输出电路,用于输出要由数据处理电路执行的指令序列;以及生成电路,用于执行生成过程以使用所述输入数据生成所述指令序列,所述指令中的至少一些指令被分组为函数,其中所述指令序列包括间接控制流指令,所述间接控制流指令包括间接控制流指令,所述间接控制流指令指示所述间接控制流指令的目标存储在何处的字段;所述目标是所述函数中的一个函数的入口点,并且所述生成过程使所述指令序列中的至少一条指令在执行所述间接控制流指令之后存储控制流推测状态。

从第二示例配置来看,提供了一种设备,所述设备包括:接收装置,用于接收输入数据;输出装置,用于输出要由处理装置执行的指令序列;以及执行装置,用于执行生成过程以使用所述输入数据生成指令序列,所述指令中的至少一些指令被分组为函数,其中所述指令序列包括用于间接地控制流的装置,所述用于间接地控制流的装置包括指示所述用于间接地控制流的装置的目标存储在何处的字段;所述目标是所述函数中的一个函数的入口点;并且所述生成过程使所述指令序列中的至少一条指令在所述用于间接地控制流的装置执行之后存储控制流推测状态。

从第三示例配置来看,提供了一种方法,所述方法包括:接收输入数据;输出要由数据处理电路执行的指令序列;以及执行生成过程以使用所述输入数据生成所述指令序列,所述指令中的至少一些指令被分组为函数,其中所述指令序列包括间接控制流指令,所述间接控制流指令包括指示所述间接控制流指令的目标存储在何处的字段;所述目标是所述函数中的一个函数的入口点,并且所述生成过程使所述指令序列中的至少一条指令在执行所述间接控制流指令之后存储控制流推测状态。

从第四示例配置来看,提供了一种可读存储介质,所述可读存储介质包括根据上述方法产生的计算机程序。

附图说明

将仅通过示例的方式,参考如附图所示的本技术的实施例来进一步描述本技术,在附图中:

图1示出了根据一些实施例的设备;

图2示出了分支指令的行为,并且用于展示一种推测执行形式;

图3示出了条件选择指令的示例;

图4a和图4b示出了根据一些实施例的将输入数据转换成包含数据值推测限制指令的输出指令序列,从而实现控制流推测未命中追踪;

图5a、图5b和图5c示出了根据一些实施例的将输入数据转换为包含跨函数调用边界的abi兼容控制流推测未命中追踪的输出指令序列;

图6示出了可以如何将涉及转换的几种技术进行组合;

图7示出了根据一些实施例的设备;

图8以流程图的形式示出了根据一些实施例的数据处理方法;

图9以流程图的形式示出了根据一些实施例的数据处理方法;

图10a示出了根据一些实施例的输入数据到输出指令序列的转换;

图10b示出了根据一些实施例的输入数据到输出指令序列的转换;

图11示意性地示出了根据一些实施例的代码块之间的关系;

图12以流程图的形式示出了根据一些实施例的数据处理方法;

图13a示意性地示出了示例类层次;

图13b示意性地示出了基于参考图13a所示的示例类层次的虚函数表的生成;

图14a示出了根据一些实施例的输入数据到输出指令序列的转换;

图14b示出了根据一些实施例的输入数据到输出指令序列的转换;

图14c示出了根据一些实施例的输入数据到输出指令序列的转换;

图15a示意性地示出了根据一些实施例的具有虚函数包装器的代码块和用于生成虚函数调用的控制流推测成功的指示符的形实转换程序之间的关系;

图15b示意性地示出了根据一些实施例的具有虚函数包装器的代码块和用于生成虚函数调用的控制流推测成功的指示符的形实转换程序的之间的关系;以及

图16以流程图的形式示出了根据一些实施例的数据处理方法。

具体实施方式

在参考附图讨论实施例之前,提供以下对实施例和相关优点的描述。

根据一个方面,提供了一种设备,该设备包括:输入电路,用于接收输入数据;输出电路,用于输出要由数据处理电路执行的指令序列;以及生成电路,用于执行生成过程以使用输入数据生成指令序列,指令中的至少一些指令被分组为函数,其中指令序列包括间接控制流指令,间接控制流指令包括指示间接控制流指令的目标存储在何处的字段;目标是函数中的一个函数的入口点,并且生成过程使指令序列中的至少一条指令在执行间接控制流指令之后存储控制流推测状态。

此类设备可以采取将输入指令转换成输出指令的编译器的形式。输入电路接收输入数据,并且输出电路输出将由数据处理电路执行的指令序列。生成电路对输入数据执行生成过程,以便生成指令序列。指令序列中的指令中的一些指令被分组为函数(例如,封装的代码块),函数具有一个或多个入口点。函数的入口点是控制流可以跳转到以实现特定任务的点。例如,函数入口序列可以在执行特定操作之前执行一些特定于上下文的初始化(例如,通过形实转换程序)。因此,此类函数可以有两个入口点—一个指向函数的开始,一个指向初始化。以这种方式,取决于使用哪个入口点,可以在有或没有初始化的情况下执行函数。生成过程使得在输出的指令被执行时指令中的至少一条指令存储控制流推测状态。这些一条或多条指令在间接控制流指令被执行之后发生,因此控制流推测状态指示针对间接控制流指令是否发生了控制流推测。输入数据可以通过生成过程从第一语言转换成第二语言,该第二语言是由数据处理电路(其可以是处理电路本身)可执行的。在其他实施例中,输入数据可以为与输出的指令序列相同的语言,并且生成过程可以使附加指令被添加以便建立控制流推测状态。

在一些实施例中,控制流推测状态指示控制流推测是否正确地发生。控制流推测可以在条件分支指令的情况下发生,其中进行分支预测以便确定是否应在提取、解码和开始执行进一步指令方面遵循该分支,直到该分支的结果为已知的。在这些实施例中,提供了指示推测是否正确地发生的指令。

在一些实施例中,指令序列中的存储控制流推测状态的至少一条指令被禁止由数据处理电路进行数据值推测。这可以通过例如提供“推测屏障”来实现,该“推测屏障”阻止在进一步的指令中使用推测的数据值,直到已经确定那些推测的数据值是正确的。如前所述,数据推测是一种用于估计数据值的技术。因此,通过在确定控制流推测状态时阻止数据值推测发生,可以确定分支实际上是否应该被遵循。

在一些实施例中,指令序列中的存储控制流推测状态的至少一条指令适于使数据处理电路执行比较并根据比较结果来存储控制流推测状态。执行比较以确定控制流推测是否应引起分支。然后,存储控制流推测状态,以便可以在其他地方的其他计算中引用或使用控制流推测状态。

在一些实施例中,输入数据包括对函数之一的调用;并且指令序列在目标处包括指令序列中的存储控制流推测状态的至少一条指令。以这种方式,可以进行控制流推测状态,以指示作为进行的函数调用的结果的对特定函数的进入是否正确地发生。

在一些实施例中,指令序列中与调用相关联的目标是通过基于调用和进行调用所针对的数据结构执行查找操作而确定的。因此,目标可以根据进行调用所针对的数据结构而不同。可以执行查找以确定目标是什么(例如,要执行的目标代码的地址或位置)。在其他实施例中,该确定可以作为数学计算的一部分来进行。与间接分支相关的其他技术对于技术人员而言将是已知的。

在一些实施例中,调用是虚函数调用;对与数据结构相关联的虚拟表执行查找操作,虚拟表包括对与数据结构相关联的虚函数的入口点的一个或多个引用;在每个入口点处,比较确定入口点的地址是否与虚拟表中存储的入口点的地址相对应。虚函数调用被认为是对函数的调用,该函数可以用包含例如面向对象的编程语言的函数的子类进行重写。此类语言包括例如c++和java。在此类情况下,由于可以重写函数,因此调用的函数取决于对象(类实例化)。例如,如果对象是超类,则可以调用一个函数,并且对象中可被调用的不同函数是子类。因此,在分支预测器的情况下,可以训练函数调用的目标,以导致到这些函数之一分支,如果呈现给函数调用的对象突然改变,则该分支可能是不正确的。这将导致推测未命中发生。然而,由于虚函数调用至少隐式地包括进行函数调用所针对的数据结构(例如,对象)作为参数,因此可以确定预期目标。因此,通过在每个目标处包括比较,可以确定当前函数是否与打算调用的函数相对应。

在一些实施例中,响应于比较结果与计算结果相对应,控制流推测状态指示控制流推测正确地发生。

在一些实施例中,指令序列的至少一个子集符合应用二进制接口;并且通过根据应用二进制接口在存储电路中存储非法值,在指令序列中的函数之间保持存储的控制流推测状态。应用二进制接口(abi)指示软件应如何使用硬件的某些元件。例如,abi可以指定调用约定(例如,如何将不同的值存储在寄存器和/或栈中以便执行函数调用或从函数调用返回)。因此,abi可以指示特定寄存器应该/不应该存储特定值。无论如何,在此类实施例中,尽管多个指令中的至少一个子集符合abi,但是将“非法”(例如,不允许的)值(根据abi)存储在存储电路中以便维持函数之间的控制流推测状态。以这种方式,由于存储电路中“非法”值的存在应没有影响,因此可以保持与现有系统的兼容性。

在一些实施例中,响应于控制流推测状态指示发生推测未命中,将非法值存储在存储电路中。由于作为推测未命中的结果,预期将发生“倒带”,因此可以认为将非法值存储在存储电路中直到倒带发生是可以接受的。应注意,在一些其他实施例中,反之亦然,即响应于控制流推测状态指示推测未命中未发生而存储非法值。

在一些实施例中,存储电路包括栈指针寄存器;并且非法值是0。在一些abi中,栈指针寄存器(可用于指向存储器中存储前一栈帧的末尾的地址)在函数调用期间不允许为0。因此,通过将值0存储在栈指针寄存器中,可以指示已经发生了推测未命中。另外,由于阻止在栈指针寄存器中存储此类值,因此在此处存储此类值值不应具有整体影响。

在一些实施例中,指令序列包括访问指令,访问指令包括访问地址;并且访问指令的正确执行取决于控制流推测状态。以这种方式,可以根据控制流推测是否应该发生来控制对数据的访问。在一些情况下,可以认为访问指令的正确执行是安全的,因为以这种方式可以禁止访问指令在不安全的情况下执行—例如在控制流推测未命中已经发生的情况下和访问数据值是不合适的情况下。这可以帮助禁止特权数据泄漏,因为如果推测未命中发生,则实际上可能无法检索到数据。

在一些实施例中,指令序列包括对访问指令之前的访问地址或由访问指令从访问地址检索到的数据执行操作的指令;并且操作取决于控制流推测状态。通过对取决于控制流推测状态的地址或数据执行操作,可以取决于控制流推测是否是正确的来影响地址或数据。如果访问不适当,则这可使得可以“破坏”地址或数据。以这种方式,由于地址无效而不发生访问,或者访问发生但是数据是无效的,使数据无法被其他指令使用。通过使地址无效,数据本身不会被检索到,这使得更难以不适当地访问数据。

有多种执行操作的方式。在一些实施例中,该操作是包括操作数的逻辑与运算;并且在控制流推测状态指示发生推测未命中的情况下,操作数是0。因此,当推测未命中发生时,执行与预算的结果是有效地使访问地址“无效”(零),从而禁止访问发生。如果根据控制流推测状态未发生推测未命中,则操作数可以是全1值(例如,存储在适当寄存器中的每个位为“1”),使得与访问地址的“与”导致访问地址本身。

现在将参考附图描述特定实施例。

图1示出了根据一些实施例的设备100。该设备可以例如采用用于执行指令的管线的形式。在图1的示例中,提供了指令提取器110。这种指令提取器例如从存储器或从指令缓存获得要执行的指令。然后,指令提取器将所提取的(一个或多个)指令传递给指令解码器120,指令解码器将所提取的指令解码并针对每个指令生成一个或多个控制信号。将控制信号传递到一个或多个保留站130a-130d。每个保留站存储与用于由执行单元140a-140d执行的指令相对应的数据。每个保留站130充当关于解码指令的队列,并且给定保留站130a中的解码指令可以由对应的执行单元140a以任何顺序来处理。在此,执行单元140包括两个算术逻辑单元(alu)140a、140b;浮点单元140c;和加载/存储单元140d。将解码的指令发送到适当的执行单元140。例如,经由对应的保留站130c将浮点指令发送到浮点单元140c。

图2示出了分支指令的行为,并且用于展示一种推测行执行形式。具体地,第一组指令200包括分支指令a。这导致流程跳转到第二组指令210。在条件分支指令(具有与之相关的条件的分支指令)的情况下,分支将仅当条件被满足时发生。如果发生分支,则执行将在分支指令b的目标处继续。在此示例中,这涉及指令d、e、f、g和h的执行。指令h充当返回指令,返回指令使分支返回。然后流程返回到第一指令块200中的指令c,其中执行重新开始。

在典型的执行中,指令提取器110可能要花费一个处理器周期来提取指令,并且指令解码器可能要花费另一处理器周期来对指令进行解码。然后,指令可以在保留站130中等待,直到获得了必要数据为止。例如,如果指令对存储器中的数据进行操作,则可能要花费几个处理器周期来从存储器中检索出数据。一旦指令已经被传递,则在执行单元140处实际执行指令可能花费另外的处理器周期。为了有效地保持,典型的数据处理系统将继续同时操作(例如,提取、解码和执行)其他指令。在此处,条件分支指令在理论上可能导致问题,因为在实际评估条件之前,不知道接下来应提取/解码/执行哪些指令。为了帮助解决此问题,进行分支预测,并且假定分支将朝一个特定方向前进。然后,提取/解码/执行该方向上的指令。如果预测是正确的,则保持效率。如果不是,则发生“倒带”,并且从正确的位置执行重新开始。在这种情况下,与仅在执行分支之前停止执行的情况相比,不会损失大量时间。这是推测性执行的示例。因此,在图2的示例中,当到达a处的分支指令时,可以在已知是否应遵循a处的分支之前执行指令b-h(并且如果执行h处的返回指令,则甚至执行c)中的一些或全部。

图3示出了条件选择指令300的示例。指令包括目的地310(例如寄存器x20)、第一源320(例如,专用寄存器xzr,其总是包含值“0”)、第二源330(例如,寄存器x20)和条件340(例如,“ge”表示“设置了大于或等于标记吗”)。大于或等于标记可以由于前一条指令比较两个值而被设置。或者,在一些实施例中,组成条件选择指令的条件340可以包括直接比较两个值。

如果未设置大于或等于标记,则执行该指令导致值0(在xzr寄存器中)被存储在寄存器x20中。否则(如果设置了大于或等于标记),将寄存器x20中的值存储在寄存器x20中(即,寄存器x20中的值保持相同)。应注意,如果条件选择指令中的条件340与条件分支指令的条件相对应,则如下所述,可以使寄存器x20中存储的值根据控制流推测执行是否正确地发生进行改变。

图4a示出了可以如何使用条件选择指令,以便通过将输入指令集400编译(例如转换)成输出指令集410来确定是否发生了推测未命中。应注意,输入指令400可以为一种语言并且输出指令410可以为第二语言,该第二语言打算在数据处理电路100(诸如图1所示的数据处理电路)上执行。

输入指令包含典型的条件分支场景。在该示例中,分支指令的条件420是设置了“大于或等于标记”。如果条件被满足,则分支发生到目标标签bb2(标签包括指令instr2)。否则,在标签bb1(其包括指令instr1)处继续执行。在输出指令中,寄存器x20最初加载有值“-1”。然后,如在输入指令中一样,分支发生。如先前参考图3所述,在目标标签bb2处,发生条件选择指令。然而,条件选择指令430的条件是分支指令中的条件420的相反—取决于被设置的“lt”(“小于”)标记。因此,条件选择指令的条件与分支指令的条件相对应,因为它们均依赖于相同的测试,而只是仅根据可能的结果采取不同的动作。然后执行分支bb2的其余指令(包括instr2)。类似地,在分支bb1处,条件选择指令440发生。如果不遵循分支指令420,则执行该代码。在这种情况下,条件选择指令440的条件与分支指令420的条件相同。

以这种方式,在分支bb1处,寄存器x20中的值或者将保持相同(“-1”),或者将被改变(改变成“0”)。因为每个条件选择指令430、440中的条件420与到达包含该条件选择指令的目标所需的分支指令420中的条件相反,因此寄存器x20的值仅当发生推测未命中时才改变。否则,寄存器x20将保持相同。例如,假设在bb2处发生推测。这在设置了“ge”标记的情况下将是正确的。在此,条件选择指令420确定是否设置了“lt”标记。假设“ge”和“lt”标记是互斥的,如果分支指令420中的条件被满足(即如果推测正确地发生),则条件选择指令420将使寄存器x20中的值保持相同(例如,通过将寄存器x20中的值移动到寄存器x20),并且bb1处的条件选择指令440也类似。在每种情况下,如果分支被正确地推测,则寄存器x20将保持值“-1”。在该示例中,csdb指令禁止在csel指令上可能发生的数据值推测被在csdb指令之后执行的任何指令观察到。这使得寄存器x20中的值准确地表示针对在执行csdb之后执行的指令的控制流预测的正确性。csdb指令是一种特殊的指令,用于防止在csdb指令之前发生的数据值推测未命中被在csdc指令之后执行的指令看到。因此,建立了csel指令的实际结果,而不是通过数据值推测来进行估计。当然,如果发生了推测未命中,则在将来的某个时间点处将发生“倒带”。然而,在此之前,意识到发生控制流推测未命中也是有用的,以便禁止特权数据泄漏。

应当理解,在相关示例中,如果推测正确地发生,则可以使改变发生;并且如果分支是推测未命中的,则保持相同。类似地,应当理解,,可以针对每种结果任意地选择具体值(例如“0”和“-1”)。

图4b示出了可以如何使用由条件选择指令产生的输出来保护对特定数据的访问。在此,假设寄存器x20包含关于推测是正确发生(全为1)还是不正确发生(全为0)的指示。在输入数据450中,进行加载以获得存储在存储器中寄存器x1中存储的存储器地址处的数据。将数据加载到寄存器x0中。在此,存储在寄存器x1中的存储器地址被认为包含特权信息,因为其与安全数据有关。因此,在控制流推测未命中发生时—即当程序员不打算加载数据时,不希望将该数据加载到寄存器x0中。输出数据460对寄存器x1中的存储器地址与存储在寄存器x20中的值执行逻辑“与”运算。在控制流推测未命中的情况下这导致x1具有值0,因此从地址0而不是特权数据的地址进行加载。

最后,加载发生在现在存储在寄存器x1中的存储器地址上。如果发生推测未命中,则对寄存器x20中的全0值进行逻辑“与”运算将导致寄存器x1中的存储器地址被擦除,从而防止加载指令对其进行访问。如果推测正确地发生,则逻辑与运算单独地保留寄存器x20中的值,从而允许值被加载指令访问。因此,保护加载,以便加载仅当推测被正确地执行时才发生。

应注意,csdb指令可以放置在寄存器x20上的最后csel操作和在与指令中第一次使用寄存器x20之间的任何位置,以保护加载特权数据的加载指令。

期望对于是否发生推测未命中的指示在函数调用之间持续存在。图5a、图5b和图5c示出了可以如何执行进一步的转换,以便使推测未命中指示符能够在函数调用期间持续存在。

在这些示例中,假设输出指令510、530、550符合应用二进制接口(abi)。这指示了底层软件应如何利用硬件。例如,它可以指定调用约定,调用约定规定应如何实现函数调用—例如,应用于将参数传递给被调用的函数的寄存器、应如何传递回结果、应如何以及何时改变程序计数器和栈指针等。在本示例中,假设(通常情况下)abi阻止跨函数(例如在调用或返回期间)将值“0”存储在栈指针中。因此,通过将值“0”存储在栈指针中,可以提供向后兼容的系统,该向后兼容的系统跨函数传达以下事实:控制流推测正确地发生或推测未命中发生。由于这使用了abi阻止的寄存器中的值,因此它不会对任何现有系统造成问题。换句话说,栈指针寄存器中的“0”的存在应该没有影响。本示例使用值“0”来指代发生了推测未命中的事实。此外,与先前所使用的寄存器x20相反,本示例在函数内使用寄存器ip1来存储指示是否发生推测未命中的值。

图5a示出了如何将输入指令500中的函数调用转换成执行函数调用的输出指令510。输出指令将当前栈指针移动到临时寄存器ip0中。然后在ip0中的栈指针值与包含控制流推测未命中值的寄存器ip1的值之间执行逻辑与操作(如果正确推测了控制流,则为全1;如果错误地推测了控制流,则为全0),并且结果被存储在临时寄存器ip0中。该与运算导致ip0包含栈指针的值(在正确的控制流推测的情况下),或0(在不正确的控制流推测的情况下)。然后,将结果存储回栈指针中。某些架构阻止在栈指针上直接进行算术/逻辑运算。在该示例中,mov指令将栈指针的值移动到临时寄存器以允许对该值进行改变。在允许对栈指针进行直接操作的其他架构上,当控制流推测未命中直接发生而无需mov指令时,可以将栈指针的值设置为0。

然后,执行分支和链接指令,这导致对标签“callee”的非条件函数调用发生。应注意,分支和链接指令不是条件分支指令,因此不会由于该分支和链接指令本身而发生推测未命中。然而,作为发生推测未命中的结果,可能输入了包含该分支和链接指令的函数。本技术使得可以跨函数保持控制流推测状态,因此在从该分支和链接指令输入的函数中,已知是否已经发生了推测未命中(根据先前的条件分支指令,未示出)。

图5b示出了callee标签处的行为。在输入指令520中,这将仅包括标签“callee:”。在由此产生的输出指令530中(例如,通过编译或转换),在栈指针与跟随有调节选择指令的值“0”之间进行比较。当栈指针为零时,即当发生控制流推测未命中时,该代码序列导致寄存器ip1包含全零。如果在此之前未发生控制流推测未命中,则栈指针将具有非零值,并且该代码序列导致ip1包含全1值。以这种方式,通过使用栈指针中的abi非法值“0”,ip1的值从在“callee”的函数调用之前转移到函数“callee”。

图5c示出了在返回指令处导致来自函数调用的返回的行为。在输入指令540中,这将仅包括指令“ret”。在由此产生的输出指令550(例如,通过编译或转换)中,将栈指针移动到临时寄存器ip0中。然后对ip0和ip1的内容执行逻辑与运算。最后,将结果移回栈指针,并发生至调用方的返回。如上所述,使用临时寄存器ip0以对存储在栈指针中的值执行操作。

返回参考图5a,输出指令510的最后两行指示返回之后在调用方处发生了什么。具体地,再次将栈指针与值“0”进行比较。如果栈指针等于“0”,则将“0”存储在ip1中(即,指示发生了控制流推测未命中),否则通过csetm指令将全1值存储在寄存器ip1中。图5a、图5b和图5c组合地展示了如何通过使用栈指针的abi非法值来跨函数调用边界传递寄存器ip1中的控制流推测未命中值。

图6示出了可以如何组合几种技术。在此,输入数据580导致标签“函数”的分支。在标签“函数”处,随后将存储器中寄存器x1所列出的地址处保存的值加载到寄存器x0中。然后在返回之前执行指令“instr1”。在输出数据590中,寄存器ip1再次在函数内使用以表示是否发生了控制流推测未命中。通过将该值放入栈指针中来在函数之间传递该值。在发生推测未命中的情况下,ip1中的值是“0”,否则是全1值。对于栈指针,当发生推测未命中时,该值是“0”,否则栈指针值保持部件(abi规则阻止该值为“0”)。如前所述,将栈指针移动到寄存器ip0中,以便可以对该栈指针进行调整。然后将其与ip1的当前值进行与运算,并移动回该栈指针。在此阶段,栈指针现在将反映控制流推测状态。然后发生函数调用(bl指令)。在“函数”中,将控制流推测状态传送回ip1。如前所述,如果控制流推测正确地发生,则寄存器“x1”中的访问地址保持不变,否则该值被“破坏”,从而阻止访问。恰好在与指令之前的csdb指令意味着ip1的值将不是在此点推测的数据值(未命中),使得当控制流推测未命中发生时,x1中的地址被破坏。然后执行指令“instr1”。最后,控制流推测状态在返回之前被存储回栈指针中。在调用函数中的返回点处,将栈指针中的控制流推测未命中指示(“0”表示推测未命中,任何非零值表示正确推测)转换回寄存器ip1中(“0”表示推测未命中,全1表示正确推测),并且其余指令的执行继续(在图6中示出为“…”)。

图7示出了根据一些实施例的用于从输入数据产生输出指令的设备600。该设备包括接收输入数据(其可以是指令的形式,可能是与输出指令不同的语言)的输入电路610。输入电路将这些指令传递到生成电路620,生成电路生成输出指令序列。输出指令序列基于输入指令。在此示例中,输出指令将实现与输入指令相同的效果,但是将具有添加的进一步的指令(具有在数据值推测上添加的至少一些约束),其导致在寄存器中追踪控制流推测未命中,如例如关于图4a、图4b、图5a、图5b和图5c中的一些或全部图所示。然后,由输出电路630输出输出指令。由输出电路630输出的指令序列被设计为在处理电路100上执行。指令序列为使得使用一个特定的例外,它们实现了abi。该一个例外是关于存储电路640(例如栈指针寄存器),被阻止在函数调用期间存储在存储电路中的值实际上在函数调用期间存储在该存储电路中,以便表示发生了(或尚未发生)推测未命中的事实。

图8示出了根据一些实施例的数据处理方法。该方法以流程图700的形式示出,并且例如可以由如图1所示的数据处理设备100执行。在步骤710处,对指令进行解码并且生成控制信号。在步骤720处,使用控制信号来执行一个或多个数据处理操作。在步骤730处,确定是否以某种方式标记了与数据处理操作相对应的控制信号(以及因此对应的指令)以禁止针对那些指令执行数据值推测。如果否,则在步骤740处允许针对那些数据处理操作进行推测。否则,在步骤750处,阻止针对那些指令进行推测。

图9示出了根据一些实施例的数据处理方法。该方法以流程图800的形式示出,并且可以例如使用如图7所示的设备600来执行。在步骤810处,接收输入数据。在步骤820处,执行生成过程。这可以对应于关于图4a、图4b、图5a、图5b和图5c示出的过程中的一些或全部过程。一个或多个输出指令使控制流推测状态在执行期间被存储。最后,在步骤830处输出生成过程的输出(输出指令序列)。

图10a示出了可以如何关于间接控制流指令来使用本技术。间接控制流指令是一种必须计算(例如查找或数学地确定)控制流指令的目标,而不是构成指令本身的一部分的指令。采用此类机制的部分原因是为了避免直接分支指令的复杂结构。例如,如果必须将变量与多个不同的值进行比较并根据每次比较执行不同的代码,则可能要耗费时间来执行一系列指令,该一系列指令将变量与第一值,然后第二值,然后第三值等进行比较以确定可以在何处找到要执行的代码。作为此的替代方案,可以执行查找表或计算以便直接确定可以在何处找到要执行的代码。图10a示出了包括开关语句的输入代码900的示例。在这种情况下,开关语句具有变量“i”,并根据“i”的值执行不同代码。例如,如果i=0,则执行代码”x=2;…;break”。如果i=1,则执行代码“x=3;…;break”等。尽管很可能使用直接分支指令来实现如此简短的代码片段,但是可以使用输出指令920中的间接控制流指令910来实现代码片段(并且我们将假设其是为了该示例的目的而实现的)。在此,间接控制流程指令910采用“switch<expr>”指令的形式,该指令在程序中向前跳过由表达式<expr>确定的行数。在此,表达式使用基于值i的映射,并且该映射使得如果i=0则程序向前跳2行,如果i=1则程序向前跳4行,如果i=2则跳6行,并且如果i=3则跳8行。例如,如果i=3,则程序向前跳8行,因此执行“sstate&=-(i==3);x=7;…;break;”。break语句使得退出该块。

与参考图4a所示的示例不同,开关语句相当于于使用针对不同结果的不同目标对变量i执行许多不同的比较。因此,基于对每个目标的不同比较来确定输出指令920中的控制流推测状态(由变量sstate表示)。每个目标处的比较“模仿了”开关语句中将导致该目标的比较。例如,当i=1时,控制流在第6行处结束(这使它从第二行向前跳了四行)。因此,通过比较变量i以查看其是否为1来确定第6行处的控制流推测状态。如果是,则sstate变为-1(全1)。如果不是,则sstate变为0。

与前面的示例一样,可以在过程中稍后使用csdb指令,以保护可能容易受到例如边信道攻击的变量。同样根据前面的示例,以sstate存储的值可用于控制对访问地址或从该访问地址检索到的数据的访问(例如,通过对这些项中的任一项和sstate的值执行逻辑“与”),以便如果sstate指示不应发生控制流推测,则访问地址或数据值将变为零。指示控制值推测是否应发生的值也可以使用例如前面示出的栈指针在函数之间传送。

图10b示出了其中i的可能值的子集指向同一目标的变型。例如,输入指令930为使得:如果i是0或1,则其执行代码“x=3;break;”,如果i是2或3,则其执行代码“x=7;break;”。在输出指令950中,间接控制流指令940提供新的经修改的映射。然而,为确定控制流推测状态而执行的比较已被调整,以检查变量是否为导致特定目标的值中的任何值。例如,如果i是0或1,则可以到达第5行处的代码。因此,如果i等于0或1,则在第5行上的代码中执行的比较将控制流推测状态设置为-1(全1),否则将其设置为0。显然,其他比较也是可能的。例如,如果值0-3中的任何值导致要分支到的目标,则该目标处的比较可以检查i是否在>=0且<=3的范围中。

应当理解,在这些示例中,间接控制流指令已经用伪代码表示。然而,将明显的是,如本领域技术人员所知,可以借助于间接分支指令和查找表来复制由usemap(<indexvariable>,<mapping>)执行的查找功能。

变量与目标之间的关系可能更复杂。图11示出了允许实现目标和变量的几乎任何组合的数据流的示例。在块1010中,基于变量i执行间接控制流指令。取决于i的值,执行不同的块1020、1030、1040、1050以设置sstate。然后,每个块分支到公共代码块1060。以这种方式,可以对每个可能的目标执行适当的比较,而不管变量的值与目标之间的关系的复杂性。

图12以流程图1100的形式示出了根据一些实施例的方法,并且方法可以使用如图7所示的设备600来说明。在步骤1110处,接收输入数据。在步骤1120处,执行生成过程。这可以与关于图10a、图10b和图11所示的过程相对应,其中技术中的一些技术是参考图4a、图4b、图5a、图5b和图5c描述的。一个或多个输出指令使控制流推测状态在执行间接控制流指令之后在执行期间被存储。最后,在步骤1130处输出生成过程的输出(输出指令序列)。

本技术还可以关于重写的继承函数来使用,例如使用虚函数调用。

图13a示出了示例类结构1200,其可以例如以面向对象的编程语言来实现。提供了基类person,其实现了两个可重写的函数—getname和getincome。类person具有两个子类—employee和pensioner。这两个类都重写基本方法getincome,从而提供了它们自身对该方法的实现。这种类结构使得对于employee型对象,当调用方法getincome时,将调用作为employee定义的一部分提供的getincome的实现。当对pensioner型对象调用方法getincome时,将调用作为pensioner定义的一部分提供的getincome的实现。相比之下,由于这两个类都不提供getname方法的实现,因此当任一类的对象调用函数getname时,这会导致作为person类的一部分的getname实现被调用。

图13b示出了基于关于图13a所示的类结构生成的虚函数表结构1240。针对person对象生成的虚函数表1250包括分别指向getname和getincome的基本实现的指针。employee虚函数表1260包括指向getname的person实现的指针和指向getincome的employee实现的指针。同时,pensioner虚函数表1270包含指向person的getname实现和pensioner自身的getincome实现的指针。

给定的程序可以在许多不同的person型对象上调用getincome函数。由于该类结构,所以每个对象可以是person型,或者可以是employee型或pensioner型(因为这些类是person的子类而也是person型)。因此,在提供了完全相同类的多个对象之后,可以将分支预测电路训练为分支到特定地址,在该地址处提供getincome的一种实现。当提供了属于其他类之一的对象时,这可导致控制流推测未命中。例如,如果前几个对象都是employee型,则可以将分支预测器训练成分支到getincome的employee实现。然而,如果下一个对象是pensioner型的对象,则经训练的分支预测器将发生推测未命中并分支到getincome的employee实现而不是getincome的pensioner实现。

图14a示出了转换代码以实现此类虚函数调用的典型方式。可以提供包含函数调用“person.getincome()”的输入数据,该输入数据导致在可能是person型的名为“person”的对象上调用方法getincome()。隐式地,这相对于调用getincome(person)以实现关于person类所提供的getincome。在实践中,输出指令获得指针thispointer,该指针引用对象本身的当前实例。这被添加到对象内部的虚函数表指针的预定偏移量。然后,将指针解除引用并存储在寄存器x1中。因此,寄存器x1有效地存储变量“person”的虚函数表地址。然后,下一行确定指向getincome函数的指针的偏移量,并将其与存储在x1中值相加,并将结果存储回x1中。然后,寄存器x1对存储在变量“person”的虚函数表中的getincome方法的位置进行存储。最后,使用x1调用分支和链接指令,以分支到变量“person”的getincome方法的实现位置。

图14b示出了可以如何改变此转换以帮助提供指示有关此类函数调用的控制流推测状态的变量。这次,不是确定指向函数getincome的指针,而是确定指向函数“vfunc_validate_pensioner_getincome”的指针。函数“vfunc_validate_pensioner_getincome”是由生成过程生成的特殊函数,以便在传递给getincome方法的实际实现之前确定控制流推测状态。

图14c示出了如何针对生成过程改变getincome方法的实现。如先前一样,提供查找操作。这确定了虚函数表的地址,以便确定指向当前变量的vfunc_validate_pensioner_getincome方法的指针所指向的地址(由指针thisptr引用)。adr指令直接获得与函数vfunc_validate_pensioner_getincome相关联的地址。然后,通过cmp指令比较这些位置。然后,可以将该比较结果作为条件选择指令csel的对象,以反映控制流推测是否正确地发生(如前所述)。同样地,如前所述,将该比较结果存储在栈指针中,以便其可以在函数之间传递。最后,对pensioner_getincome的实际实现进行了分支。因此,通过将打算调用的函数(其可以由于在进行函数调用时隐式传递“this”对象而被确定)与实际调用的函数(其可以根据adr指令确定)进行比较,可以比较应调用的函数是否实际被调用,由此作为虚函数调用的结果,控制流推测是正确地发生还是不正确地发生。

图15a示出了在使用形实转换程序处理多继承的情况下可以如何扩展过程,这是在几种面向对象的语言(例如c++)中使用。在这些情况中,在第一代码块1300中进行初始查找和函数调用。这导致包装器1320被调用,包装器1320检查控制值推测是否正确地发生。这存储了指示在跳到形实转换程序1340之前推测是否正确地发生的状态。然后,形实转换程序1340进行任何必要的更正,以处置多继承。最后,形实转换程序跳到该函数的实际实现1360。当实现1360返回时,其返回到主代码块1300。应当理解,存在许多不同的入口点。第一入口点1310在包装器块1320的开始处。第二入口点1330在形实转换程序块1340的开始处,并且第三入口点1350在实现块1360的开始处。根据要执行的初始化的量可以使用入口点1310、1330、1350中的每个入口点。例如,如果不进行推测未命中检查,则可以使用第二入口点1330。

本领域技术人员应理解,在一些情况下(例如,如果不使用多继承的话)可以省略形实转换程序。在这种情况下,包装器块1320将直接跳到实现块1360的入口点1350。

图15b示出了另一种实现方式。在这种情况下,不是提供完整链,而是主代码块1370调用包装器块1380。这执行检查并存储指示控制流推测是否正确地发生的状态。然后,该相同函数执行形实转换程序1340的功能。然后,该相同函数在返回到主代码块1370之前执行实现1360。在此示例中,包装器块再次包含多个入口点。在存储控制流推测状态的代码的开始处提供第一入口点1385。在处理多继承的代码的开始处提供第二入口点1390。在执行该实现的代码的开始处提供第三入口点1395。

图16示出了根据一些实施例的数据处理方法。该方法以流程图1500的形式示出,并且可以例如使用如图7所示的设备600来执行。在步骤1510处,接收输入数据。在步骤1520处,执行生成过程。这可以对应于例如关于图14a、图14b或图14c中的任何一个所示出的过程,并且可以结合关于图4a、图4b、图5a、图5b和图5c示出的技术中的一些或全部技术。一个或多个输出指令使得在执行其目标是函数(例如虚函数)的间接控制流指令之后的执行期间存储控制流推测状态。最后,在步骤1530处输出生成过程的输出。

该设备还可以以多种其他方式配置。

在一些实施例中,提供了一种设备,该设备包括:输入电路,用于接收输入数据;输出电路,输出要由数据处理电路执行的指令序列,所述指令中的至少一些指令被分组为函数;以及生成电路,用于执行生成过程以使用所述输入数据生成所述指令序列,其中所述生成过程使所述指令序列中的至少一条指令存储在执行所述指令序列期间执行的控制流推测状态;并且在所述函数之间保持所存储的控制流推测状态。此类设备可以采取将输入指令转换成输出指令的编译器的形式。输入电路接收输入数据,并且输出电路输出要由数据处理电路执行的指令序列。生成电路对输入数据执行生成过程,以便生成指令序列。生成过程使在输出的指令被执行时所述指令中的至少一条指令存储控制流推测状态。在函数之间保持该状态,例如在函数调用期间和从函数调用返回期间。在这种情况下,在一个函数中建立的推测状态可以在另一个函数中被访问。输入数据可以通过生成过程从第一语言转换成第二语言,该第二语言是由数据处理电路(其可以是处理电路本身)可执行的。在其他实施例中,输入数据可以采用与输出的指令序列相同的语言,并且生成过程可以使附加指令被添加以便建立控制流推测状态。

在一些实施例中,控制流推测状态指示控制流推测是否正确地发生。控制流推测可在条件分支指令的情况下发生,其中进行分支预测以便确定是否应在提取、解码和开始执行进一步的指令方面遵循该分支,直到该分支的结果为已知的。在这些实施例中,提供了指示推测是否正确地发生的指令。

在一些实施例中,指令序列中的存储控制流推测状态的至少一条指令被禁止经受数据处理电路的数据值推测。这可以通过例如提供“推测屏障”来实现,该推测屏障阻止在进一步的指令中使用推测的数据值,直到已经确定那些推测的数据值是正确的。如前所述,数据推测是一种用于估计数据值的技术。因此,通过在确定控制流推测状态时阻止数据值推测发生,可以确定是否应该实际上遵循分支。

在一些实施例中,指令序列中的存储所述控制流推测状态的至少一条指令适于使数据处理电路执行比较并根据比较结果来存储控制流推测状态。执行比较以确定控制流推测是否应引起分支。然后,存储控制流推测状态,以便可以在其他地方的其他计算中引用或使用它。

在一些实施例中,输入数据包括条件分支指令,该条件分支指令包括条件和当满足该条件时分支到的目标;并且指令序列在目标处包括指令序列中的存储控制流推测状态的至少一条指令。存储控制流推测状态的指令发生在可能经受控制流推测的分支指令之后。因此,在发生控制流推测的情况下,可以确定分支的决定是否正确。

在一些实施例中,比较在逻辑上与条件相对应。应当理解,如果由确定控制流推测状态的指令执行的比较与条件分支指令中的条件匹配,则控制流推测状态与是否应采取条件分支相匹配。在此,术语“在逻辑上与……相对应”是指条件和比较具有逻辑等价性。如本领域技术人员将知道的,这可以使用布尔真值表来建立。

在一些实施例中,响应于比较结果与未满足的条件相对应,控制流推测状态指示控制流推测不正确地发生。

在一些实施例中,指令序列的至少一个子集符合应用二进制接口;通过根据应用二进制接口将非法值存储在存储电路中,在函数之间保持所存储的控制流推测状态。应用二进制接口(abi)指示软件应如何使用硬件的某些元件。例如,abi可以指定调用约定(例如,如何将不同的值存储在寄存器和/或栈中以便执行函数调用或从函数调用返回)。因此,abi可以指示特定寄存器应该/不应该存储特定值。无论如何,在此类实施例中,尽管多个指令中的至少一个子集符合abi,但是“非法”(例如,不允许的)值(根据abi)被存储在存储电路中以便维持函数之间的控制流推测状态。以这种方式,由于存储电路中“非法”值的存在应没有影响,因此可以保持与现有系统的兼容性。

在一些实施例中,通过根据应用二进制接口存储合法值,在函数中的至少一些函数内保持所存储的控制流推测状态。在一些实施例中,在函数之间,合法值存储在存储非法值的同一存储电路中。然而,在一些实施例中,在函数内,合法值存储在不同存储电路中。

在一些实施例中,响应于控制流推测状态指示发生推测未命中,将非法值存储在存储电路中。由于作为推测未命中的结果,预期将发生“倒带”,因此可以认为将非法值存储在存储电路中直到倒带发生是可以接受的。应注意的是,在一些其他实施例中,反之亦然,即,响应于控制流推测状态指示推测未命中未发生而存储非法值。

在一些实施例中,存储电路包括寄存器。例如,在一些实施例中,存储电路包括栈指针寄存器;并且非法值是0。在一些abi中,栈指针寄存器(可用于指向存储器中存储前一栈帧的末尾的地址)在函数调用期间不允许为0。因此,通过将值0存储在栈指针寄存器中,可以指示发生了推测未命中。另外,由于阻止在栈指针寄存器中存储此类值,因此在此处存储此类值不应具有整体影响。

在一些实施例中,指令序列包括访问指令,该访问指令包括访问地址;并且访问指令的正确执行取决于控制流推测状态。以这种方式,可以根据控制流推测是否应该发送来控制对数据的访问。在一些情况下,可以认为访问指令的正确执行是安全的,因为以这种方式可以禁止访问指令在不安全的情况下执行—例如在控制流推测未命中发生的情况下和访问数据值是不合适的情况下。这可以帮助禁止特权数据泄漏,因为如果推测未命中发生,则实际上可能无法检索数据。

在一些实施例中,指令序列包括在访问指令之前对访问地址执行操作的指令;并且该操作取决于控制流推测状态。通过对取决于控制流推测状态的地址执行操作,可以取决于控制流推测是否正确来影响该地址。如果访问是不适当的,则这可使得可能“破坏”地址,使得不发生访问,从而防止数据被检索到。

存在多种方法可以执行操作。在一些实施例中,该操作是包括操作数的逻辑与运算;并且在控制流推测状态指示发生推测未命中的情况下,操作数是0。因此,当推测未命中发生时,执行与运算的结果是有效地使访问地址“无效”(零),从而禁止访问发生。如果根据控制流推测状态未发生推测未命中,则操作数可以是全1值(例如,存储在适当寄存器中的每个位为“1”),使得与访问地址的“与”导致访问地址本身。

保护数据的另一种方式是在检索到数据之后对数据本身执行操作。因此,在一些实施例中,指令序列包括对由访问指令从访问地址检索到的数据执行操作的指令;并且操作取决于控制流推测状态。再次,例如,在一些实施例中,该操作是包括操作数的逻辑与运算;并且在控制流推测状态指示发生推测未命中的情况下,操作数是0。因此,在检索到数据后,如果指示发生了推测未命中,则立即收到使该数据无效(零)的与运算的影响。

在本申请中,词语“被配置为……”用于表示设备的元件具有能够执行所定义的操作的配置。在本文中,“配置”是指硬件或软件互连的布置或方式。例如,该设备可以具有提供所定义操作的专用硬件,或者处理器或其他处理装置可以被编程以执行功能。“被配置为”并不意味着需要以任何方式改变设备元件以提供所定义的操作。

尽管本文已经参考附图详细描述了本发明的说明性实施例,但是应当理解,本发明不于这些精确的实施例,并且在不脱离由所附权利要求书限定的本发明的范围和精神的情况下,本领域的技术人员可以对这些实施例进行各种改变、添加和修改。例如,在不脱离本发明的范围的情况下,可以将从属权利要求的特征与独立权利要求的特征进行各种组合。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1