How to use INVLPG on x86-64 architecture?

别等时光非礼了梦想. 提交于 2019-12-12 19:16:11

问题


I'm trying to measure memory access timings and need to reduce the noise produced by TLB hits and misses

In order to clear a specific page out of the TLB I tried to use the INVLPG instruction, following those two examples: http://wiki.osdev.org/Paging and http://wiki.osdev.org/Inline_Assembly/Examples

I wrote the following code:

static inline void __native_flush_tlb_single(unsigned long addr)
{
   asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
}

But the resulting binary throws an SIGSEGV on execution. As I prefere Intel syntax, I had a look at the particular disassembly:

invlpg BYTE PTR [rdi]

If I understand this correctly, invlpg will be called with the byte value at RDI, but would rather require a QWORD address.

However the second link says "The m pointer points to a logical address, not a physical or virtual one: an offset for your ds segment"

So INVLPG needs an offset from the ds segment? But the ds segment isn't used in AMD64 anymore, is it?

Can someone explain me how to use the INVLPG instruction with AMD64 or how to evict an TLB entry on this architecture?


回答1:


The SIGSEGV happens because INVLPG is a privileged instruction and can only be called out of kernel code (Thanks Cody Gray).

In order to demonstrate the use of INVLPG I wrote a little LKM invlpg_mod.c :

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <linux/types.h>

// LICENSE
MODULE_LICENSE("GPL");

static inline void invlpg(unsigned long addr) {
    asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
}


// init module
static int __init module_load(void) {
    int mem;
    invlpg((unsigned long) &mem);
    printk("Evicted %p from TLB", &mem);
}


//unload modules
static void __exit module_unload(void) {
    printk("Goodbye.");
}

module_init(module_load);
module_exit(module_unload);

Make sure you have the linux-headers installed and build the LKM with this Makefile:

KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)

obj-m = invlpg_mod.o

all:
    make -C $(KDIR) M=$(PWD) modules

clean:
    make -C $(KDIR) M=$(PWD) clean

Load the LKM with:

 sudo insmod invlpg_mod.ko

And unload it:

sudo rmmod invlpg_mod.ko

See the output:

dmesg | tail


来源:https://stackoverflow.com/questions/37752664/how-to-use-invlpg-on-x86-64-architecture

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!