Reputation: 6853
Flushing the cache and TLB does not work. The following kernel module receives a pid and flushes the tlb/cache entries for the process with that id.
I modified the handle_mm_fault()
function in the Linux kernel and added a line to it that prints out the pid and the address that caused a page if(current->pid == target_process)
....see the line commented out below. However, when I run the test I do not see any page faults caused by that process. I am using linux v3.11.6 running on x86-64bit processor.
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
static int pid = -1;
module_param(pid, int, 0444);
void do_init(void) {
struct task_struct *task;
struct vm_area_struct *next_vma;
struct mm_struct *mm;
if (pid == -1)
return;
task = pid_task(find_vpid(pid), PIDTYPE_PID);
//target_process = pid;
if (!task) {
printk("Could not find the task struct for process id %d\n", pid);
return;
} else {
printk("Found the task <%s>\n", task->comm);
}
mm = task->mm;
if (!mm) {
printk("Could not find the mmap struct for process id %d\n", pid);
return;
}
printk("****Start_brk = %lu\n", mm->start_brk);
down_read(&mm->mmap_sem);
next_vma = find_vma(mm, mm->start_brk);
flush_cache_mm(mm);
flush_tlb_mm(mm);
up_read(&mm->mmap_sem);
}
int init_module(void) {
printk("Inserting the module!!!\n");
do_init();
return 0;
}
void cleanup_module(void) {
printk("Module removed!!!\n");
}
MODULE_LICENSE("GPL");
Upvotes: 0
Views: 2510
Reputation: 94255
Flushing the cache and TLB does not work.
Actually it may work, but effect of TLB flushing is not getting page faults. After TLB was flushed, memory access from the target process will result in TLB miss and TLB refill. In most common x86/x86_64 and more common ARM, Memory management unit will refill TLB in hardware, without active code from OS. In refill MMU will load page table and do a walk through it. In more exotic SPARC or MIPS tlb refill may be done by software, but not by pagefault.
If you want to force page faults on accesses to some memory region, you may (from userspace) use mprotect
syscall (check its man, just set no read (PROT_READ) and write (PROT_WRITE) access in the flags.
If you want to do the same from kernel space, you can check the implementation of mprotect
: SYSCALL_DEFINE3(mprotect in mm/mprotect.c and do the same...
unsigned long vm_flags = calc_vm_prot_bits(..flags..); // set flags
down_write(¤t->mm->mmap_sem); // lock mm
vma = find_vma(current->mm, ..address..); // find needed VMA
// check for errors...
vma->vm_flags = newflags;
vma->vm_page_prot = pgprot_modify(...) // update vm flags, or just call mprotect_fixup
up_write(¤t->mm->mmap_sem); // unlock mm
^^^ the code is not tested, not valid and should not be used by anyone.
Upvotes: 1