MIPS 是一个缓存不透明的架构设计,通常设计存在两个 Cache,即 指令 Cache 与 数据 Cache。在装载完代码执行前(一般仅应用程序动态生成的代码需要,如 JIT)一定要刷新指令 Cache,确保 Cache 中指令与写入的一致。这个过程分两个步骤:1. 是将数据 Cache 中的数据写回 RAM。2. 将 RAM 中的数据装载到指令 Cache。
较早的实现依赖于 cache 指令,但 cache 指令是个特权指令,事实上并不是需要做这件事的程序都是特权程序,所以普通应用程序在 Linux 平台上可以调用系统调用 cacheflush,进入特权模式完成刷新操作。
上述方法虽然可行,但如果频繁的执行系统调用效率较低,所以在 MIPS r2 的 ISA 中增加了一条常规特权下的 synci 指令,专门用于做这件事。它的用法是:
synci offset(base)
要求对每个 Cache Line 执行一次 synci 操作。
例程
void
cache_flush (void *code, size_t size)
{
long start, end, line_size, mask;
__asm__ volatile (
".set push \t\n"
".set noreorder \t\n"
"rdhwr %[line_size], $1 \t\n"
"addu %[end], %[code], %[size] \t\n"
"subu %[mask], $0, %[line_size] \t\n"
"and %[end], %[end], %[mask] \t\n"
"and %[start], %[code], %[mask] \t\n"
"addu %[end], %[end], %[line_size] \t\n"
"1: \t\n"
"subu %[end], %[end], %[line_size] \t\n"
"bne %[start], %[end], 1b \t\n"
"synci 0(%[end]) \t\n"
".set pop \t\n"
:[start]"=&r"(start), [end]"=&r"(end),
[line_size]"=&r"(line_size), [mask]"=&r"(mask)
:[code]"r"(code), [size]"r"(size)
);
}
Over!