背景技术
高速缓存(Cache)是当前中央处理器(CPU)中必不可少的组成部分,
因为计算机系统中,内存(Memory)的处理速度远低于CPU,为了弥补两
者的速度差异,就必须在CPU中增加Cache。增加Cache功能的依据是局部
性原理,即程序的地址访问流有很强的时序相关性,CPU要访问的下一个内
存单元大部分情况在上一次访问的地址附近。
Cache功能主要包括正确地进行读写,该功能完全由硬件来完成的。一
般CPU对内存的访问分为两种,一种是需要得到下一条指令(机器码),
另一种是需要得到数据。在CPU中的Cache分为两级,在一级Cache中,
又分为指令高速缓存(Code Cache)和数据高速缓存(Data Cache),分别
对应于上述两种需要。当在一级Cache中没有得到所要的内容时(称为没有
命中),会在二级Cache中寻找。二级Cache通常不区分指令(Code)和数
据(Data),如仍未命中,则真正到内存中寻找。对于虚拟内存系统,还有
可能最终在磁盘中寻找。
CPU在出厂时一般都要经过基于硬件的Cache测试,但是为了保证CPU
装配到计算机中,并在计算机上安装操作系统后,其Cache仍然能够正常工
作,就需要在整机的环境中利用软件对Cache进行测试。由于Cache的工作
是基于硬件方式的,所以在利用软件对其进行测试时就只能采用间接方法。
其中,指令高速缓存是专门存放可执行程序的指令部分的高速缓存,通常在
操作系统下,对它进行测试的方法为利用汇编程序写一系列特殊的函数,编
译在可执行程序中,反复更改某寄存器的值,最后通过校验该值是否为预想
值来判断Cache功能是否正常,校验内容包括读和写内存时Cache起到的作
用。
然而,现有技术的对指令高速缓存的测试方法有着十分明显的缺陷,首
先,汇编程序生成的机器码的代码大小不可直接控制,而不同CPU的Cache
大小不一定相同,测试不同大小的Cache需要使用不同大小的代码,针对这
种情况,传统方法只能写几个不同的静态函数,生成不同大小机器码集,但
这种测试方法显然不能满足不断升级换代的Cache,测试指令高速缓存要求
机器码的代码量是可以在运行时动态变化和控制的;其次,在大部分操作系
统下,例如Windows95以上的操作系统,有多进程和多线程等并发机制,以
及利用磁盘存储器扩充内存的虚拟内存机制,这样,系统下可以同时运行多
个程序,CPU会分时运行正在运行的程序,当CPU从一个进程转换到另一
个进程时,其指令高速缓存中的内容会被刷新,然而由于该刷新不受控制,
所以测试程序对系统当前运行的代码不能完全控制。
此时,就需要一种测试时机器的代码量可变且受控制的指令高速缓存测
试方法解决上述问题。
附图说明
图1是本发明的指令高速缓存的测试方法的总体流程图;
图2是本发明所提出的向该内存空间内写入可执行机器码的流程图;
图3是本发明所提出的把该可执行机器码当作测试函数来执行测试的流
程图;
图4是本发明所提出的释放该段内存空间的流程图;
图5是本发明所提出的实例的在现有技术下执行代码自修改(Code
Self-Modifying)测试的流程图;及
图6是本发明所提出的实例的使用本发明的方法执行自修改(Self
Modifying)测试的流程图。
其中,附图标记说明如下:
步骤110为测试分配一段内存空间
步骤120向该内存空间内写入可执行机器码
步骤130把该可执行机器码当作测试函数来执行测试
步骤140验证该测试函数的执行结果
步骤150释放该段内存空间
步骤210写入保护现场及寄存器初始化机器码
步骤220重复写入测试函数主体机器码
步骤230写入将寄存器值存入栈中的机器码
步骤240写入恢复现场机器码
步骤250写入返回指令
步骤310将指定的内存地址压栈
步骤320执行这段机器码来完成测试函数的执行
步骤330将寄存器值出栈,存入指定内存内
步骤410如果测试尚未完成,则返回为测试分配一段内存空间之步
骤,继续执行其它测试函数
步骤420如果测试全部完成,则结束测试
步骤510执行Code Self-Modifying的测试程序1
步骤520执行Code Self-Modifying的测试程序2
步骤530执行Code Self-Modifying的测试程序3
步骤610为测试分配一段内存空间
步骤620向内存内写入Code Self-Modifying测试的代码(机器码)
步骤630执行Code Self-Modifying的测试程序
步骤640验证测试的执行结果
步骤650释放该段内存空间
具体实施方式
下面结合附图对本发明进行详细说明:
通过图1来说明,该图是本发明的指令高速缓存的测试方法的总体流程
图,说明如下:
首先为测试分配一段内存空间(步骤110) 然后向该内存空间内写入
可执行机器码(步骤120);再把该可执行机器码当作测试函数来执行测试
(步骤130) 接下来,验证该测试函数的执行结果(步骤140);最后释
放该段内存空间(步骤150)。
本发明所提供的测试方法,通过直接向内存中写入可执行机器码来生成
测试函数的机制来使测试时机器的代码量可变且受控制。该测试函数为一动
态函数,其可在操作系统基础之上,当执行测试时,首先在堆栈(Heap)中
为测试分配一段内存空间;然后直接写入一段可执行的机器码,该机器码符
合函数的规范,其中含有压栈指令和返回(ret)指令,用于执行相应功能测
试的机器码,例如该机器码可以为代码自修改测试(Code Self-Modifying)
的机器码代码,或者为其它指令高速缓存的功能性测试代码;最后把该机器
码当作测试函数来执行测试。
其中,向内存中写入机器码时,所对应的测试函数模式可以根据测试的
需求进行变化,包括固定模式和随机模式两种:在固定模式下将生成固定大
小测试机器码;而在随机模式下将生成任意变化大小的测试机器码。同时,
测试函数要改写的寄存器也可以根据需求制定为相同或者不同的寄存器。
测试完毕后,需要对测试结果进行验证,其是通过校验寄存器中的内容
是否正确,从而确定Cache是否工作正常。
下面,进一步说明本发明的流程。
请参见图2,该图是本发明所提出的向该内存空间内写入可执行机器码
的流程图,说明如下:
首先写入保护现场及寄存器初始化机器码(步骤210);然后重复写入
测试函数主体机器码(步骤220);再写入将寄存器值存入栈中的机器码(步
骤230);写入恢复现场机器码(步骤240);最后写入返回指令(步骤250)。
该测试函数的初始化机器码中,含有压栈指令,其用来保护现场,将当
前寄存器中内容压栈。
在内存空间内重复写入测试机器码的次数与对测试机器码长度的要求
有关,当要求该机器码较长时,写入和执行的次数相应较多,反之则次数较
少。若该测试机器码为固定长度的代码时,则该次数是一定的。
其中,步骤220所述的重复写入机器码的动作是指重复写入函数体,即
多次重复写入相同的主体机器码,用写入次数来控制整个函数对应机器码的
长度。在随机写入模式下,产生一个随机数,对它分配一个与其大小相适应
的内存空间,根据此内存空间的大小,确定需要写入机器码的次数,直至写
入的机器码能够填满此内存空间;同理,还可以是递增或者固定模式。但对
于函数头和函数尾,则只需写入一次。
之后,写入一段把函数执行完成之后的寄存器值保留在栈中的机器码,
以便将来把他们存入指定内存中,再进行验证。
最后,写入一段将寄存器恢复为该测试函数执行前的数值的机器码及返
回指令,从而恢复现场,退出函数。
请参见图3,该图是本发明所提出的把该可执行机器码当作测试函数来
执行测试的流程图,说明如下:
首先将指定的内存地址压栈(步骤310);然后执行写入的机器码来完
成测试函数的执行(步骤320);最后将寄存器值出栈,存入指定内存内(步
骤330)。
步骤310和步骤330是为了将函数执行结束时的寄存器中值存入内存
中。首先把指定的内存地址压入栈中,待步骤320执行完毕后,由于步骤230
的执行,寄存器中的值已经被保存在栈中,最后步骤330将栈中寄存器的值
存到了指定的内存中。
请参见图4,该图是本发明所提出的释放该段内存空间后的执行步骤流
程图,说明如下:
如果测试尚未完成,则返回为测试分配一段内存空间的步骤,继续执行
其它测试函数的步骤(步骤410);如果测试全部完成,则结束测试的步骤
(步骤420)。
当一段测试完成后,测试函数将会对测试情况进行确认,当所有测试都
已经测试完毕后,将结束本次测试;否则将重新为尚未进行的测试分配一段
内存空间,继续进行测试,直到测试全部完成为止。
下面用一种较佳的实例来说明本发明的流程。
对指令高速缓存测试的方法通常有代码复位测试(Code Replacement
Test),代码自修改测试(Code Self-Modifying Test)及代码监测测试(Code
Snoop Test)等方法。下面以代码自修改测试(Code Self-Modifying Test)作
为实施例来说明本发明的过程。
请参见图5,该图是本发明所提出的实例的在现有技术下执行代码自修
改测试(Code Self-Modifying)的流程图,说明如下:
在现有技术下,传统测试方法流程是执行不同的代码自修改测试程序,
这些程序是事先用汇编写好并编译的大小不同的执行体,不能根据实际的测
试情况来改变大小,实时地生成大小不同的执行体,其执行过程如下:执行
代码自修改测试的测试程序1(步骤510);执行代码自修改测试的测试程
序2(步骤520);执行代码自修改测试的测试程序3(步骤530)。直到所
有的代码自修改测试的测试程序执行完毕为止。
同时,代码自修改测试的测试程序与程序主体比较接近,程序运行时,
程序只需从主体中跳到该函数中运行即可,二者在内存中的地址有可能很
近,从而指令高速缓存中的内容可能并不刷新。
请参见图6,该图是本发明所提出的实例使用本发明的方法执行代码自
修改测试的流程图,说明如下:
本发明所提供的方法,其执行过程如下:
首先为测试分配一段内存空间(步骤610);然后向内存内写入Code代
码自修改测试(Self-Modifying)的代码(机器码)(步骤620);再执行代
码自修改测试(Code Self-Modifying)的测试程序(步骤630);接下来,验
证测试的执行结果(步骤640);最后释放该段内存空间(步骤650)。
其中,写入及执行代码自修改测试(Code Self-Modifying)的测试程序
还包括如下步骤:首先写入函数初始化的机器码,如压栈等指令;然后重复
写入动作,直至代码自修改测试(Self-Modifying Code)的机器码全部写入,
其写入次数根据所要求的代码长度来决定;再写入将寄存器值存入栈中的机
器码以及恢复现场和返回的机器码;再执行测试函数,返回后将寄存器值出
栈存入指定内存内;最后进行校验等其它处理。
代码自修改测试代码(Self-Modifying Code)是一种特殊的函数,执行
时代码将更改代码本身,例如,其代码如下:
add edx,0Ch 得到*指令的地址
and dword ptr[edx],ebx 改变*指令,自减1变自加1
nop 空操作
*dec eax 寄存器eax自减1
nop 空操作
如上述代码所示,第二句代码将更改第四句,把原来的eax寄存器自减
1改为自加1。这个过程是通过第一句的相加指令(add)将第四句指令(带
*号的语句)的地址放 edx寄存器,然后通过第二句的与指令(and)对该
地址指向的内容与ebx寄存器中的内容进行与运算,这样,就改变了第四句
指令的内容,本实施例中,是将原第四句的自减指令(dec eax)修改为自加
1指令(inc eax);最后通过校验eax寄存器的内容是否正确,来确定Cache
功能是否正常。上述代码将不断重复执行,其执行测试由代码长度决定。
当需要实现对Cache功能不同方面的测试时,可以改用别的代码替换代
码自修改测试代码(Self-Modifying Code),同样,可以通过控制反复次数
来控制整体代码长度。
当测试程序运行时,首先分配内存,在系统的堆栈中分配,再向其中写
入想要执行的机器码,然后程序跳转到堆栈(Heap)中执行,执行完毕后回
到跳转处执行后边的指令,再次执行该模块,或者释放所分配的内存并结束
程序。这样每次跳转会到不同的内存位置,指令高速缓存中的内容会被刷新,
从而更有效进行测试。
以上所述,仅为本发明的较佳实施例而已,并非用来限定本发明的实施
范围;所有依本发明说明书和附图内容所作的均等变化与修饰,均包含在本
发明的专利范围内。